From 11491200b2a30d6e552c1840f6aafa7a6ebd9c47 Mon Sep 17 00:00:00 2001 From: davematias Date: Wed, 7 Feb 2018 11:40:01 +0000 Subject: [PATCH 001/318] fix apple submission details --- interface.html | 4 ++-- js/interface.js | 26 +++++++++++++------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/interface.html b/interface.html index a3580bf..18291a3 100644 --- a/interface.html +++ b/interface.html @@ -644,7 +644,7 @@

Apple developer account details and distribution certificates
- app-developer@fliplet.com - log out + - log out
@@ -1271,7 +1271,7 @@

Apple developer account details and distribution certificates
- app-developer@fliplet.com - log out + - log out
diff --git a/js/interface.js b/js/interface.js index 512528e..e7bfc2d 100644 --- a/js/interface.js +++ b/js/interface.js @@ -978,13 +978,13 @@ function refreshAppStoreOptions(devEmail, devPass, selectedTeamId, selectedTeamN } //if we dont have any credentials we need to check previous result for a credential object - if(appStoreSubmission.data.previousResults && (appStoreSubmission.data.previousResults.p12 || appStoreSubmission.data.previousResults.certificate) && appStoreSubmission.data['fl-store-teamId'] === selectedTeamId) { + if(!_.isUndefined(appStoreSubmission.data.previousResults) && (!_.isUndefined(appStoreSubmission.data.previousResults.p12) || !_.isUndefined(appStoreSubmission.data.previousResults.certificate)) && appStoreSubmission.data['fl-store-teamId'] === selectedTeamId) { return { teamId: selectedTeamId, teamName: selectedTeamName, certSigningRequest: appStoreSubmission.data.previousResults.certSigningRequest, - p12: appStoreSubmission.data.previousResults.p12, - certificate: appStoreSubmission.data.previousResults.certificate, + p12: appStoreSubmission.data.previousResults.p12.files[0], + certificate: appStoreSubmission.data.previousResults.certificate.files[0], content: appStoreSubmission.data.previousResults.content }; } @@ -1060,13 +1060,13 @@ function refreshAppEnterpriseOptions(devEmail, devPass, selectedTeamId, selected } //if we dont have any credentials we need to check previous result for a credential object - if(enterpriseSubmission.data.previousResults && (latestSubmission.data.previousResults.p12 || enterpriseSubmission.data.previousResults.certificate) && enterpriseSubmission.data['fl-ent-teamId'] === selectedTeamId) { + if(!_.isUndefined(enterpriseSubmission.data.previousResults) && (!_.isUndefined(latestSubmission.data.previousResults.p12) || !_.isUndefined(enterpriseSubmission.data.previousResults.certificate)) && enterpriseSubmission.data['fl-ent-teamId'] === selectedTeamId) { return { teamId: selectedTeamId, teamName: selectedTeamName, certSigningRequest: enterpriseSubmission.data.previousResults.certSigningRequest, - p12: enterpriseSubmission.data.previousResults.p12, - certificate: enterpriseSubmission.data.previousResults.certificate, + p12: enterpriseSubmission.data.previousResults.p12.files[0], + certificate: enterpriseSubmission.data.previousResults.certificate.files[0], content: enterpriseSubmission.data.previousResults.content }; } @@ -1094,13 +1094,13 @@ function getCompletedSubmissions(organizationId, devEmail, teamId, teamName) { return new Date(sub.updatedAt).getTime(); }); - if(latestSubmission && latestSubmission.data.previousResults && (latestSubmission.data.previousResults.p12 || latestSubmission.data.previousResults.certificate)) { + if(!_.isUndefined(latestSubmission) && !_.isUndefined(latestSubmission.data.previousResults) && (!_.isUndefined(latestSubmission.data.previousResults.p12) || !_.isUndefined(latestSubmission.data.previousResults.certificate))) { return { teamId: teamId, teamName: teamName, certSigningRequest: latestSubmission.data.previousResults.certSigningRequest, - p12: latestSubmission.data.previousResults.p12, - certificate: latestSubmission.data.previousResults.certificate, + p12: latestSubmission.data.previousResults.p12.files[0], + certificate: latestSubmission.data.previousResults.certificate.files[0], content: latestSubmission.data.previousResults.content }; } @@ -1494,7 +1494,7 @@ $('.login-appStore-button').on('click', function() { $this.html('Log in'); $this.removeClass('disabled'); - $('.appStore-logged-emai').html(devEmail); + $('.appStore-logged-email').html(devEmail); $('.appStore-login-details').addClass('hidden'); $('.appStore-logged-in, .appStore-teams').addClass('show'); appStoreLoggedIn = true; @@ -1525,7 +1525,7 @@ $('.login-appStore-button').on('click', function() { $('.log-out-appStore').on('click', function() { appStoreLoggedIn = false; - $('.appStore-logged-emai').html(''); + $('.appStore-logged-email').html(''); $('.appStore-login-details').removeClass('hidden'); $('.appStore-logged-in, .appStore-more-options, .appStore-teams').removeClass('show'); }); @@ -1723,7 +1723,7 @@ $('.login-enterprise-button').on('click', function() { $this.html('Log in'); $this.removeClass('disabled'); - $('.enterprise-logged-emai').html(devEmail); + $('.enterprise-logged-email').html(devEmail); $('.enterprise-login-details').addClass('hidden'); $('.enterprise-logged-in, .enterprise-more-options, .enterprise-teams').addClass('show'); enterpriseLoggedIn = true; @@ -1752,7 +1752,7 @@ $('.login-enterprise-button').on('click', function() { $('.log-out-enterprise').on('click', function() { enterpriseLoggedIn = false; - $('.enterprise-logged-emai').html(''); + $('.enterprise-logged-email').html(''); $('.enterprise-login-details').removeClass('hidden'); $('.enterprise-logged-in, .enterprise-more-options, .enterprise-teams').removeClass('show'); }); From eb34cfff5c4463345a144e57477e5edb676d5a72 Mon Sep 17 00:00:00 2001 From: davematias Date: Wed, 7 Feb 2018 17:56:13 +0000 Subject: [PATCH 002/318] fix undefined variable --- js/interface.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/interface.js b/js/interface.js index e7bfc2d..adaa1ac 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1060,7 +1060,7 @@ function refreshAppEnterpriseOptions(devEmail, devPass, selectedTeamId, selected } //if we dont have any credentials we need to check previous result for a credential object - if(!_.isUndefined(enterpriseSubmission.data.previousResults) && (!_.isUndefined(latestSubmission.data.previousResults.p12) || !_.isUndefined(enterpriseSubmission.data.previousResults.certificate)) && enterpriseSubmission.data['fl-ent-teamId'] === selectedTeamId) { + if(!_.isUndefined(enterpriseSubmission.data.previousResults) && (!_.isUndefined(enterpriseSubmission.data.previousResults.p12) || !_.isUndefined(enterpriseSubmission.data.previousResults.certificate)) && enterpriseSubmission.data['fl-ent-teamId'] === selectedTeamId) { return { teamId: selectedTeamId, teamName: selectedTeamName, From 783461b830d4b116ef09a33f0f8488130e92a358 Mon Sep 17 00:00:00 2001 From: davematias Date: Mon, 12 Feb 2018 18:26:53 +0000 Subject: [PATCH 003/318] Added missing validator changes --- vendor/validator.js | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/vendor/validator.js b/vendor/validator.js index b881fea..05f1a3a 100755 --- a/vendor/validator.js +++ b/vendor/validator.js @@ -41,6 +41,14 @@ getValue($this) && $this.trigger('input.bs.validator') }) }) + this.$element.find('[data-nomatch]').each(function () { + var $this = $(this) + var target = $this.attr('data-nomatch') + + $(target).on('input.bs.validator', function (e) { + getValue($this) && $this.trigger('input.bs.validator') + }) + }) // run validators for fields with values, but don't clobber server-side errors this.$inputs.filter(function () { @@ -64,7 +72,8 @@ custom: {}, errors: { match: 'Does not match', - minlength: 'Not long enough' + minlength: 'Not long enough', + nomatch: 'Can not match' }, feedback: { success: 'glyphicon-ok', @@ -83,6 +92,10 @@ var target = $el.attr('data-match') return $el.val() !== $(target).val() && Validator.DEFAULTS.errors.match }, + 'nomatch': function ($el) { + var target = $el.attr('data-nomatch') + return $el.val() === $(target).val() && Validator.DEFAULTS.errors.nomatch + }, 'minlength': function ($el) { var minlength = $el.attr('data-minlength') return $el.val().length < minlength && Validator.DEFAULTS.errors.minlength @@ -391,4 +404,4 @@ }) }) -}(jQuery); +}(jQuery); \ No newline at end of file From d5671824a84855a8546b4f3cc0308b769d4a09a3 Mon Sep 17 00:00:00 2001 From: hcarneiro Date: Wed, 14 Feb 2018 12:09:18 +0000 Subject: [PATCH 004/318] Fixes push data being saved after submission --- js/interface.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/js/interface.js b/js/interface.js index adaa1ac..4dc1d07 100644 --- a/js/interface.js +++ b/js/interface.js @@ -713,6 +713,8 @@ function saveAppStoreData(request) { appStoreSubmission.data = data; notificationSettings = pushData; + savePushData(true); + if (request) { requestBuild('appStore', appStoreSubmission); } else { @@ -795,6 +797,8 @@ function saveEnterpriseData(request) { enterpriseSubmission.data = data; notificationSettings = pushData; + savePushData(true); + if (request) { requestBuild('enterprise', enterpriseSubmission); } else { @@ -806,6 +810,8 @@ function saveEnterpriseData(request) { enterpriseSubmission.data = data; notificationSettings = pushData; + savePushData(true); + if (request) { requestBuild('enterprise', enterpriseSubmission); } else { @@ -833,7 +839,7 @@ function saveUnsignedData(request) { } } -function savePushData() { +function savePushData(silentSave) { var data = notificationSettings; $('#pushConfiguration [name]').each(function(i, el) { @@ -860,7 +866,7 @@ function savePushData() { data: notificationSettings }).then(function() { $('.save-push-progress').addClass('saved'); - if (!notificationSettings.apn) { + if (!notificationSettings.apn && !silentSave) { alert('Your settings have been saved!\n\nHowever push notifications will only work on App Store and Enterprise apps.\nRequest an app for one of those types and fill in the Bundle ID and Team/Team ID fields.\n\nYou don\'t need to request another app if you have requested an app for App Store or Enterprise before with those two fields filled in already.'); } From b9cb663e59e9c5fe5496cd1e6b97ed7daa13baa4 Mon Sep 17 00:00:00 2001 From: davematias Date: Thu, 15 Feb 2018 18:02:27 +0000 Subject: [PATCH 005/318] Added char limit and editable mode --- interface.html | 7 ++----- js/interface.js | 4 ++-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/interface.html b/interface.html index 18291a3..bfde08a 100644 --- a/interface.html +++ b/interface.html @@ -45,13 +45,10 @@

Reviewer Notes

Additional information about your app that can help during the review process. If your app is secured, be sure to provide login details or credentials - the reviewer needs them to test your app.

@@ -1034,7 +1053,7 @@

Reviewer Notes

-
+ diff --git a/js/interface.js b/js/interface.js index da9ebbb..b64de1f 100644 --- a/js/interface.js +++ b/js/interface.js @@ -170,6 +170,15 @@ function loadAppStoreData() { return; } + /* Manual release */ + if (name === "fl-store-manualReview") { + if (!_.isUndefined(appStoreSubmission.data[name])) { + $('#' + name).prop('checked', appStoreSubmission.data[name]); + } + + return; + } + $('[name="' + name + '"]').val((typeof appStoreSubmission.data[name] !== "undefined") ? appStoreSubmission.data[name] : ''); }); @@ -803,6 +812,12 @@ function saveAppStoreData(request) { return; } + /* Manual release */ + if (name === "fl-store-manualReview") { + data[name] = $('[name="'+name+'"]').is(':checked'); + return; + } + if (name === 'fl-store-distribution') { var newValue = $('[name="'+name+'"]:checked').val(); if (newValue === 'previous-file') { From 2db3b4bade742fa99fdf6a2ddd8a31971495d7fd Mon Sep 17 00:00:00 2001 From: davematias Date: Fri, 2 Mar 2018 16:42:01 +0000 Subject: [PATCH 021/318] Changed property name as it creates confusion with other fastlane options --- interface.html | 4 ++-- js/interface.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface.html b/interface.html index 93271ce..4d6eba8 100644 --- a/interface.html +++ b/interface.html @@ -979,8 +979,8 @@

Release Configuration

- -
diff --git a/js/interface.js b/js/interface.js index b64de1f..0c6c6c2 100644 --- a/js/interface.js +++ b/js/interface.js @@ -171,7 +171,7 @@ function loadAppStoreData() { } /* Manual release */ - if (name === "fl-store-manualReview") { + if (name === "fl-store-manualRelease") { if (!_.isUndefined(appStoreSubmission.data[name])) { $('#' + name).prop('checked', appStoreSubmission.data[name]); } @@ -813,7 +813,7 @@ function saveAppStoreData(request) { } /* Manual release */ - if (name === "fl-store-manualReview") { + if (name === "fl-store-manualRelease") { data[name] = $('[name="'+name+'"]').is(':checked'); return; } From 5446a34798c5a2ac26512840c30d80654b268897 Mon Sep 17 00:00:00 2001 From: davematias Date: Mon, 5 Mar 2018 11:31:17 +0000 Subject: [PATCH 022/318] Added missing maxlenght validators --- interface.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface.html b/interface.html index 4d6eba8..ade8558 100644 --- a/interface.html +++ b/interface.html @@ -530,7 +530,7 @@
- +

Eg: 2008 Acme Inc.

@@ -694,7 +694,7 @@

App version and bundle ID

This is the version number of your app and will be displayed on the App Store listing.

- +

The recommended format for version number is 1.0.0. With a maximum value of 99 per number.

@@ -1033,7 +1033,7 @@

Reviewer Notes

Optional

- +
@@ -1042,7 +1042,7 @@

Reviewer Notes

Optional

- +
From b60e9948c65cc97197165f29457c80ac9913675a Mon Sep 17 00:00:00 2001 From: davematias Date: Mon, 5 Mar 2018 12:39:12 +0000 Subject: [PATCH 023/318] added info on certificates --- interface.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface.html b/interface.html index ade8558..eac044b 100644 --- a/interface.html +++ b/interface.html @@ -625,7 +625,7 @@

Apple developer account details and distribution certificates

- For more information on this topic see the Support Documents. + The certificate file cannot be password protected. For more information on certificates topic see the Support Documents.

From 986dce1f85cf35311fce962b33fb186cc95abb58 Mon Sep 17 00:00:00 2001 From: davematias Date: Mon, 5 Mar 2018 16:12:44 +0000 Subject: [PATCH 024/318] Theam lists are different for app store and enterprise --- js/interface.js | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/js/interface.js b/js/interface.js index 9decd76..7a517de 100644 --- a/js/interface.js +++ b/js/interface.js @@ -231,13 +231,10 @@ function loadAppStoreData() { } function appStoreTeamSetup(devEmail, loginButton) { - return getTeams(organizationID, appStoreSubmission.id) - .then(function(teams) { - var appStoreTeams = _.filter(teams, function(team) { - return team.type === "Company/Organization"; - }) - appStoreTeams.forEach(function(team, i) { - $('.appStore-team').append(''); + return getTeams(organizationID, appStoreSubmission.id, true) + .then(function(teams) { + teams.forEach(function(team, i) { + $('.appStore-team').append(''); }); $('#fl-store-appDevLogin').removeClass('disabled'); @@ -350,7 +347,7 @@ function loadEnterpriseData() { } function enterpriseTeamSetup(devEmail, loginButton) { - return getTeams(organizationID, enterpriseSubmission.id) + return getTeams(organizationID, enterpriseSubmission.id, false) .then(function(teams) { var enterpriseTeams = _.filter(teams, function(team) { return team.type === "In-House"; @@ -1036,10 +1033,10 @@ function setCredentials(organizationId, id, data, verify = true) { }) } -function getTeams(organizationId, id) { +function getTeams(organizationId, id, isItunes) { return Fliplet.API.request({ method: 'GET', - url: 'v1/organizations/' + organizationId + '/credentials/submission-' + id + '/teams?itunes=false' + url: 'v1/organizations/' + organizationId + '/credentials/submission-' + id + '/teams?itunes=' + isItunes }) .then(function(result) { return Promise.resolve(result.teams); From 6bc09586a243c8f06fb3a8e06d50d76acb7e6550 Mon Sep 17 00:00:00 2001 From: davematias Date: Mon, 5 Mar 2018 16:57:00 +0000 Subject: [PATCH 025/318] Improved itunes team filter --- js/interface.js | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/js/interface.js b/js/interface.js index 7a517de..622b4ca 100644 --- a/js/interface.js +++ b/js/interface.js @@ -232,9 +232,24 @@ function loadAppStoreData() { function appStoreTeamSetup(devEmail, loginButton) { return getTeams(organizationID, appStoreSubmission.id, true) - .then(function(teams) { - teams.forEach(function(team, i) { - $('.appStore-team').append(''); + .then(function(itunesTeams) { + var allPromises = []; + var portalTeamsPromise = getTeams(organizationID, appStoreSubmission.id, false); + allPromises.push(portalTeamsPromise); + allPromises.push(Promise.resolve(itunesTeams)); + + return Promise.all(allPromises); + }) + .then(function(teams) { + var appStoreTeams = _.filter(teams[0], function(team) { + var itunesTeam = _.find(teams[1], function(itcTeam) { + return itcTeam.team_name === team.name; + }); + + return team.type === "Company/Organization" && !_.isUndefined(itunesTeam); + }) + appStoreTeams.forEach(function(team, i) { + $('.appStore-team').append(''); }); $('#fl-store-appDevLogin').removeClass('disabled'); From b6848f221d09872ecb5b7b95bb67720b78fa7eef Mon Sep 17 00:00:00 2001 From: davematias Date: Tue, 6 Mar 2018 15:00:21 +0000 Subject: [PATCH 026/318] Added fail message to the interface if it exists --- interface.html | 9 ++++++--- js/interface.js | 4 ++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/interface.html b/interface.html index 003ce00..3f8b1cb 100644 --- a/interface.html +++ b/interface.html @@ -1618,12 +1618,15 @@

App submission status

\{{/if}} \{{#if failed}} -
Failed
- +
Failed
\{{#if updatedAt}} Finished on: \{{updatedAt}}\{{/if}} -
There was an error building your app
+ \{{#if message}} +
\{{message}}
+ \{{else}} +
There was an error building your app
+ \{{/if}} \{{/if}} \{{#if cancelled}} diff --git a/js/interface.js b/js/interface.js index 622b4ca..0c32904 100644 --- a/js/interface.js +++ b/js/interface.js @@ -2245,6 +2245,10 @@ function checkSubmissionStatus(origin, iosSubmissions) { build[submission.status] = true; build.fileUrl = appBuild ? appBuild.url : ''; + if (submission.result.message) { + build.message = submission.result.message; + } + if (userInfo.user && (userInfo.user.isAdmin || userInfo.user.isImpersonating)) { build.debugFileUrl = debugHtmlPage ? debugHtmlPage.url : ''; } From 14ead6c59325219cec4e12e0e6e4469cebe406eb Mon Sep 17 00:00:00 2001 From: hcarneiro Date: Wed, 7 Mar 2018 15:02:09 +0000 Subject: [PATCH 027/318] Testing status copy enhanced --- interface.html | 4 ++-- js/interface.js | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/interface.html b/interface.html index f138da4..1b8f489 100644 --- a/interface.html +++ b/interface.html @@ -1577,7 +1577,7 @@

App submission status

\{{/if}} \{{#if ready-for-testing}} -
Ready for testing
+
\{{testingStatus}}
\{{#if fileUrl}} \{{/if}} \{{#if debugFileUrl}} @@ -1585,7 +1585,7 @@

App submission status

\{{#if updatedAt}} Ready on: \{{updatedAt}}\{{/if}} -
App ready for testing
+
\{{testingMessage}}
\{{/if}} \{{#if tested}} diff --git a/js/interface.js b/js/interface.js index 5c6207f..612db16 100644 --- a/js/interface.js +++ b/js/interface.js @@ -2096,6 +2096,19 @@ function checkSubmissionStatus(origin, iosSubmissions) { var appBuild; var debugHtmlPage; + // Default copy for testing status for different users + if (submission.status === 'ready-for-testing') { + if (userInfo.user && (userInfo.user.isAdmin || userInfo.user.isImpersonating)) { + // Fliplet users + build.testingStatus = 'Ready for testing'; + build.testingMessage = 'App is ready for testing'; + } else { + // Normal users + build.testingStatus = 'In testing'; + build.testingMessage = 'Your app is being tested by Fliplet'; + } + } + if (submission.result.appBuild && submission.result.appBuild.files) { appBuild = _.find(submission.result.appBuild.files, function(file) { var dotIndex = file.url.lastIndexOf('.'); From a669e0e0a6bbde88ad6677630c0de362d70dd486 Mon Sep 17 00:00:00 2001 From: davematias Date: Wed, 7 Mar 2018 16:27:02 +0000 Subject: [PATCH 028/318] Removed app icon name input limit --- interface.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface.html b/interface.html index 3f8b1cb..6752656 100644 --- a/interface.html +++ b/interface.html @@ -134,12 +134,12 @@
From d611c7ccace2b8adfa0114b35666e279fa472166 Mon Sep 17 00:00:00 2001 From: Joao-pina-fernandes Date: Tue, 13 Mar 2018 11:46:05 +0000 Subject: [PATCH 029/318] In the cases that we don't have the credentials object, p12 fetch fixed We now fetch the first completed submission that has the correct certification values (in store) or published on Enterprise. --- js/interface.js | 146 ++++++++++++++++++++++++++++-------------------- 1 file changed, 86 insertions(+), 60 deletions(-) diff --git a/js/interface.js b/js/interface.js index ec3cf44..54077ec 100644 --- a/js/interface.js +++ b/js/interface.js @@ -11,6 +11,8 @@ var appStoreCertificateCreated = false; var appStoreCertificateReplaced = false; var enterpriseCertificateCreated = false; var enterpriseCertificateReplaced = false; +var previousAppStoreSubmission = {}; +var previousEnterpriseStoreSubmission = {}; var appStorePreviousCredential = undefined; var appStoreFileField = undefined; var appStoreTeamId = undefined; @@ -84,9 +86,9 @@ function loadAppStoreData() { var hasAppId = !_.isUndefined(appStoreSubmission.data['iTunesAppId']); /* APP NAME */ - if (name === "fl-store-appName") { + if (name === "fl-store-appName") { $('[name="' + name + '"]').val(!_.isUndefined(appStoreSubmission.data[name]) ? appStoreSubmission.data[name] : appName); - + if (!_.isUndefined($('[name="' + name + '"]').val()) && hasAppId) { $('[name="' + name + '"]').attr('readonly', 'readonly'); } @@ -121,7 +123,7 @@ function loadAppStoreData() { if (name === "fl-store-language" && !_.isUndefined($('[name="' + name + '"]').val()) && (hasAppId || appStoreSubmissionInStore)) { $('.dll-store-language').addClass('hidden'); $('#fl-store-language').prop('required', false); - $('.fl-store-language-placeholder').removeClass('hidden'); + $('.fl-store-language-placeholder').removeClass('hidden'); } return; } @@ -173,8 +175,8 @@ function loadAppStoreData() { /* Manual release */ if (name === "fl-store-manualRelease") { if (!_.isUndefined(appStoreSubmission.data[name])) { - $('#' + name).prop('checked', appStoreSubmission.data[name]); - } + $('#' + name).prop('checked', appStoreSubmission.data[name]); + } return; } @@ -216,15 +218,15 @@ function loadAppStoreData() { var $loginButton = $('.login-appStore-button'); $loginButton.html('Logging in'); $loginButton.addClass('disabled'); - $('#fl-store-appDevPass').addClass('disabled'); + $('#fl-store-appDevPass').addClass('disabled'); $('#fl-store-appDevLogin').addClass('disabled'); - getCredential(organizationID, appStoreSubmission.data['fl-credentials']).then(function (credential) { + getCredential(organizationID, appStoreSubmission.data['fl-credentials']).then(function (credential) { return appStoreTeamSetup(credential.email, $loginButton); }).catch(function (error) { //we don't need to handle errors for automatic login $loginButton.html('Log in'); $('#fl-store-appDevLogin').removeClass('disabled'); - $('#fl-store-appDevPass').removeClass('disabled'); + $('#fl-store-appDevPass').removeClass('disabled'); $loginButton.removeClass('disabled'); Fliplet.Widget.autosize(); }); @@ -251,11 +253,11 @@ function appStoreTeamSetup(devEmail, loginButton) { appStoreTeams.forEach(function(team, i) { $('.appStore-team').append(''); }); - + $('#fl-store-appDevLogin').removeClass('disabled'); - $('#fl-store-appDevPass').removeClass('disabled'); + $('#fl-store-appDevPass').removeClass('disabled'); $('#fl-store-appDevLogin').val(devEmail); - $('#fl-store-appDevPass').prop('required', false); + $('#fl-store-appDevPass').prop('required', false); loginButton.html('Log in'); loginButton.removeClass('disabled'); $('.appStore-logged-email').html(devEmail); @@ -349,7 +351,7 @@ function loadEnterpriseData() { $loginButton.addClass('disabled'); $('#fl-ent-appDevLogin').addClass('disabled'); $('#fl-ent-appDevPass').addClass('disabled'); - getCredential(organizationID, enterpriseSubmission.data['fl-credentials']).then(function (credential) { + getCredential(organizationID, enterpriseSubmission.data['fl-credentials']).then(function (credential) { return enterpriseTeamSetup(credential.email, $loginButton); }).catch(function (error) { //we don't need to handle errors for automatic login @@ -476,7 +478,7 @@ function submissionBuild(appSubmission, origin) { // Auto increments the version number and saves the submission var newVersionNumber = incrementVersionNumber(appStoreSubmission.data['fl-store-versionNumber']); $('[name="fl-store-versionNumber"]').val(newVersionNumber); - + saveAppStoreData(); $('#fl-store-teams').val(''); $('.appStore-more-options').removeClass('show'); @@ -547,12 +549,12 @@ function save(origin, submission) { .then(function(newSubmission) { var cloneCredentialsPromise = Promise.resolve(); - if (origin === "appStore") { + if (origin === "appStore") { newSubmission.data['fl-credentials'] = 'submission-' + newSubmission.id; appStoreSubmission = newSubmission; cloneCredentialsPromise = cloneCredentials(organizationID, previousCredentials, appStoreSubmission); } - if (origin === "enterprise") { + if (origin === "enterprise") { newSubmission.data['fl-credentials'] = 'submission-' + newSubmission.id; enterpriseSubmission = newSubmission; cloneCredentialsPromise = cloneCredentials(organizationID, previousCredentials, enterpriseSubmission); @@ -568,8 +570,8 @@ function save(origin, submission) { setTimeout(function() { $('.save-' + origin + '-progress').removeClass('saved'); }, 4000); - }); - }); + }); + }); }); } @@ -825,7 +827,7 @@ function saveAppStoreData(request) { } /* Manual release */ - if (name === "fl-store-manualRelease") { + if (name === "fl-store-manualRelease") { data[name] = $('[name="'+name+'"]').is(':checked'); return; } @@ -1028,10 +1030,10 @@ function cloneCredentials(organizationId, credentialKey, submission, saveData) { } }).then(() => { if (saveData) { - return Fliplet.App.Submissions.update(submission.id, submission.data); - } + return Fliplet.App.Submissions.update(submission.id, submission.data); + } - return Promise.resolve(); + return Promise.resolve(); }).catch(() => { //do nothing, a new credential will be created after the user logs in }); @@ -1112,7 +1114,7 @@ function refreshAppStoreOptions(devEmail, selectedTeamId, selectedTeamName) { } return searchCredentials(organizationID, { - email: devEmail, + email: devEmail, type: 'apple', teamId: selectedTeamId }) @@ -1142,16 +1144,21 @@ function refreshAppStoreOptions(devEmail, selectedTeamId, selectedTeamName) { if(credential) { return credential; } + var previousResults = appStoreSubmission.data.previousResults; + //make sure that previous results are obtained from latest completed submission. + if (!_.isUndefined(previousAppStoreSubmission)) { + previousResults = previousAppStoreSubmission.result; + } //if we dont have any credentials we need to check previous result for a credential object - if(!_.isUndefined(appStoreSubmission.data.previousResults) && (!_.isUndefined(appStoreSubmission.data.previousResults.p12) || !_.isUndefined(appStoreSubmission.data.previousResults.certificate)) && appStoreSubmission.data['fl-store-teamId'] === selectedTeamId) { + if(!_.isUndefined(previousResults) && (!_.isUndefined(previousResults.p12) || !_.isUndefined(previousResults.certificate)) && appStoreSubmission.data['fl-store-teamId'] === selectedTeamId) { return { teamId: selectedTeamId, teamName: selectedTeamName, - certSigningRequest: appStoreSubmission.data.previousResults.certSigningRequest, - p12: appStoreSubmission.data.previousResults.p12.files[0], - certificate: appStoreSubmission.data.previousResults.certificate.files[0], - content: appStoreSubmission.data.previousResults.content + certSigningRequest: previousResults.certSigningRequest, + p12: previousResults.p12.files[0], + certificate: previousResults.certificate.files[0], + content: previousResults.content }; } @@ -1193,7 +1200,7 @@ function refreshAppEnterpriseOptions(devEmail, selectedTeamId, selectedTeamName) } return searchCredentials(organizationID, { - email: devEmail, + email: devEmail, type: 'apple-enterprise', teamId: selectedTeamId }) @@ -1223,16 +1230,20 @@ function refreshAppEnterpriseOptions(devEmail, selectedTeamId, selectedTeamName) if(credential) { return credential; } - + var previousResults = enterpriseSubmission.data.previousResults; + //make sure that previous results are obtained from latest completed submission. + if (!_.isUndefined(previousEnterpriseStoreSubmission)) { + previousResults = previousEnterpriseStoreSubmission.result; + } //if we dont have any credentials we need to check previous result for a credential object - if(!_.isUndefined(enterpriseSubmission.data.previousResults) && (!_.isUndefined(enterpriseSubmission.data.previousResults.p12) || !_.isUndefined(enterpriseSubmission.data.previousResults.certificate)) && enterpriseSubmission.data['fl-ent-teamId'] === selectedTeamId) { + if(!_.isUndefined(previousResults) && (!_.isUndefined(previousResults.p12) || !_.isUndefined(previousResults.certificate)) && enterpriseSubmission.data['fl-ent-teamId'] === selectedTeamId) { return { teamId: selectedTeamId, teamName: selectedTeamName, - certSigningRequest: enterpriseSubmission.data.previousResults.certSigningRequest, - p12: enterpriseSubmission.data.previousResults.p12.files[0], - certificate: enterpriseSubmission.data.previousResults.certificate.files[0], - content: enterpriseSubmission.data.previousResults.content + certSigningRequest: previousResults.certSigningRequest, + p12: previousResults.p12.files[0], + certificate: previousResults.certificate.files[0], + content: previousResults.content }; } @@ -1363,14 +1374,14 @@ function checkGroupErrors() { }); } -function validateScreenshots() { +function validateScreenshots() { var imageErrors = []; var supportedFormats = [[1242,2208], [2048,2732], [2732,2048]]; var allScreenShots = _.concat(screenShotsMobile, screenShotsTablet); _.forEach(allScreenShots, function(screenshot, key) { var supportedSize = _.find(supportedFormats, function(format) { - return format[0] === screenshot.size[0] && format[1] === screenshot.size[1]; + return format[0] === screenshot.size[0] && format[1] === screenshot.size[1]; }); if (!screenshot.appId && !supportedSize) { @@ -1380,8 +1391,8 @@ function validateScreenshots() { if (imageErrors.length > 0) { imageErrors.unshift('The following screenshots have an invalid size:'); - imageErrors.push('Supported screenshot sizes are:'); - imageErrors.push('1242 x 2208 | 2048 x 2732 | 2732 x 2048'); + imageErrors.push('Supported screenshot sizes are:'); + imageErrors.push('1242 x 2208 | 2048 x 2732 | 2732 x 2048'); var errorMessage = _.join(imageErrors, '\n\r'); alert(errorMessage); return false; @@ -1530,7 +1541,7 @@ $('#appStoreConfiguration').validator().on('submit', function(event) { if (appInfo && appInfo.productionAppId) { if (allAppData.indexOf('appStore') > -1) { - if (appStoreLoggedIn) { + if (appStoreLoggedIn) { var certificateKind = $('[name="fl-store-distribution"]:checked').val(); if (certificateKind === 'generate-file' && !appStoreCertificateCreated) { @@ -1582,7 +1593,7 @@ $('#enterpriseConfiguration').validator().on('submit', function(event) { alert('Please log in with the Apple Developer Account or choose to enter the data manually.'); return; } - + var credentialKind = $('[name="fl-ent-distribution"]:checked').val(); if (credentialKind === 'generate-file' && !enterpriseCertificateCreated) { @@ -1723,7 +1734,7 @@ $('.login-appStore-button').on('click', function() { }); $('.log-out-appStore').on('click', function() { - setCredentials(organizationID, appStoreSubmission.id, { + setCredentials(organizationID, appStoreSubmission.id, { email: null, password: null, teamId: null @@ -1733,7 +1744,7 @@ $('.log-out-appStore').on('click', function() { $('.appStore-logged-email').html(''); $('.appStore-login-details').removeClass('hidden'); $('.appStore-logged-in, .appStore-more-options, .appStore-teams').removeClass('show'); - }); + }); }); $('[name="fl-store-distribution"]').on('change', function() { @@ -1782,7 +1793,7 @@ $('#fl-store-teams').on('change', function() { $('.appStore-upload-certificate').addClass('disabled'); } - var devEmail = $('#fl-store-appDevLogin').val(); + var devEmail = $('#fl-store-appDevLogin').val(); return refreshAppStoreOptions(devEmail, value, teamName); }); @@ -1915,7 +1926,7 @@ $('.login-enterprise-button').on('click', function() { }) .then(function() { $('[name="fl-ent-distribution"][value="generate-file"]').prop('checked', true).trigger('change'); - return enterpriseTeamSetup(devEmail, $this); + return enterpriseTeamSetup(devEmail, $this); }) .catch(function(error) { if (error.responseJSON) { @@ -1928,8 +1939,8 @@ $('.login-enterprise-button').on('click', function() { } }); -$('.log-out-enterprise').on('click', function() { - setCredentials(organizationID, enterpriseSubmission.id, { +$('.log-out-enterprise').on('click', function() { + setCredentials(organizationID, enterpriseSubmission.id, { email: null, password: null, teamId: null @@ -1938,8 +1949,8 @@ $('.log-out-enterprise').on('click', function() { $('#fl-ent-appDevPass').prop('required', true); $('.enterprise-logged-email').html(''); $('.enterprise-login-details').removeClass('hidden'); - $('.enterprise-logged-in, .enterprise-more-options, .enterprise-teams').removeClass('show'); - }); + $('.enterprise-logged-in, .enterprise-more-options, .enterprise-teams').removeClass('show'); + }); }); $('[name="fl-ent-distribution"]').on('change', function() { @@ -2002,7 +2013,7 @@ $('.enterprise-generate-cert').on('click', function() { teamId: teamId, teamName: teamName }) - .then(function() { + .then(function() { return createCertificates(organizationID, enterpriseSubmission.id) .then(function(response) { enterpriseCertificateCreated = true; @@ -2138,7 +2149,7 @@ $(document).on('click', '[data-cancel-build-id]', function() { $('.browse-files').on('click', function(e) { e.preventDefault(); - + Fliplet.Studio.emit('overlay', { name: 'widget', options: { @@ -2211,7 +2222,7 @@ function checkSubmissionStatus(origin, iosSubmissions) { build.testingMessage = 'Your app is being tested by Fliplet'; } } - + if (submission.result.appBuild && submission.result.appBuild.files) { appBuild = _.find(submission.result.appBuild.files, function(file) { var dotIndex = file.url.lastIndexOf('.'); @@ -2276,12 +2287,19 @@ function checkSubmissionStatus(origin, iosSubmissions) { } function submissionChecker(submissions) { + debugger; + var asub = _.filter(submissions, function(submission) { return submission.data.submissionType === "appStore" && submission.platform === "ios"; }); var completedAsub = _.filter(asub, function(submission) { - return submission.data.status === "completed"; + return submission.status === "completed"; + }); + + //Get the Submission data from the first completed submission, it has the certification values that are in use on the app store. + previousAppStoreSubmission = _.minBy(completedAsub, function(el) { + return el.id; }); appStoreSubmissionInStore = (completedAsub.length > 0); @@ -2295,8 +2313,8 @@ function submissionChecker(submissions) { if (!appStoreSubmission) { appStoreSubmission = {}; } - - var cloneAppStoreCredentialsPromise = Promise.resolve(); + + var cloneAppStoreCredentialsPromise = Promise.resolve(); if (appStoreSubmission.data && !appStoreSubmission.data['fl-credentials']) { var prevSubCred = _.filter(asub, function(submission) { @@ -2307,17 +2325,25 @@ function submissionChecker(submissions) { return new Date(el.createdAt).getTime(); }); - appStoreSubmission.data['fl-credentials'] = 'submission-' + appStoreSubmission.id; + appStoreSubmission.data['fl-credentials'] = 'submission-' + appStoreSubmission.id; if(previousSubWithCredentials) { cloneAppStoreCredentialsPromise = cloneCredentials(organizationID, previousSubWithCredentials.data['fl-credentials'], appStoreSubmission, true); - } + } } var esub = _.filter(submissions, function(submission) { return submission.data.submissionType === "enterprise" && submission.platform === "ios"; }); + var completedEsub = _.filter(esub, function(submission) { + return submission.status === "completed"; + }); + //Get the Submission data from the first completed submission, it has certification values that are in use on the developer portal. + previousEnterpriseStoreSubmission = _.minBy(completedEsub, function(el) { + return el.id; + }); + checkSubmissionStatus("enterprise", esub); enterpriseSubmission = _.maxBy(esub, function(el) { @@ -2327,8 +2353,8 @@ function submissionChecker(submissions) { if (!enterpriseSubmission) { enterpriseSubmission = {}; } - - var cloneEnterpriseCredentialsPromise = Promise.resolve(); + + var cloneEnterpriseCredentialsPromise = Promise.resolve(); if (enterpriseSubmission.data && !enterpriseSubmission.data['fl-credentials']) { var prevSubCred = _.filter(esub, function(submission) { @@ -2339,7 +2365,7 @@ function submissionChecker(submissions) { return new Date(el.createdAt).getTime(); }); - enterpriseSubmission.data['fl-credentials'] = 'submission-' + enterpriseSubmission.id; + enterpriseSubmission.data['fl-credentials'] = 'submission-' + enterpriseSubmission.id; if(previousSubWithCredentials) { cloneEnterpriseCredentialsPromise = cloneCredentials(organizationID, previousSubWithCredentials.data['fl-credentials'], enterpriseSubmission, true); @@ -2480,7 +2506,7 @@ function initialLoad(initial, timeout) { }) .then(function(user) { userInfo = user; - return submissionChecker(submissions); + return submissionChecker(submissions); }); }) .then(function() { From 47f6e3aff9ef7e7746fed407483af658f5b9f355 Mon Sep 17 00:00:00 2001 From: Joao-pina-fernandes Date: Tue, 13 Mar 2018 12:14:18 +0000 Subject: [PATCH 030/318] removing debugger --- js/interface.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/js/interface.js b/js/interface.js index 54077ec..0ce3314 100644 --- a/js/interface.js +++ b/js/interface.js @@ -2287,8 +2287,6 @@ function checkSubmissionStatus(origin, iosSubmissions) { } function submissionChecker(submissions) { - debugger; - var asub = _.filter(submissions, function(submission) { return submission.data.submissionType === "appStore" && submission.platform === "ios"; }); From 82a353d66409c900ff74131cc8b35584c6b95f50 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Fri, 23 Mar 2018 15:07:54 +0000 Subject: [PATCH 031/318] Ensures user is uploading new screenshots for validation to apply --- js/interface.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/interface.js b/js/interface.js index 0ce3314..4f799c5 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1530,7 +1530,7 @@ $('#appStoreConfiguration').validator().on('submit', function(event) { event.preventDefault(); - if (!haveScreenshots) { + if ($('[name="fl-store-screenshots"]:checked').val() === 'new' && !haveScreenshots) { alert('You need to add screenshots before submitting'); return; } From d1c50e89dd1d54bc8d6030ad739fa90b4dd70113 Mon Sep 17 00:00:00 2001 From: Ian Broom Date: Mon, 16 Apr 2018 13:20:54 +0100 Subject: [PATCH 032/318] Added default reviewer notes, made field mandatory --- interface.html | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/interface.html b/interface.html index 22119e2..fd754f3 100644 --- a/interface.html +++ b/interface.html @@ -1051,7 +1051,24 @@

Reviewer Notes

Optional

- +

@@ -1645,4 +1662,4 @@

App submission status

- \ No newline at end of file + From a16153813e4dd09cc3aa0186a6920e511dd3286f Mon Sep 17 00:00:00 2001 From: Nicholas Valbusa Date: Wed, 18 Apr 2018 10:56:13 +0200 Subject: [PATCH 033/318] removed required attribute --- interface.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface.html b/interface.html index fd754f3..c62e97a 100644 --- a/interface.html +++ b/interface.html @@ -1051,8 +1051,7 @@

Reviewer Notes

Optional

- - A description of your app, detailing features and functionality. It will also be used for your Apple Watch app. limited to 80 characters -
- - -
-
- -
-
- - A description of your app, detailing features and functionality. It will also be used for your Apple Watch app. -
-
- -
-
- -
-
- - One or more keywords that describe your app. Keywords make App Store search results more accurate. Separate keywords with a comma. There is a limit of 100 characters -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- - -
-
- -
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
- -
-
- -
- -
- - -
-
- - -
-
-
-
- -
-
- -
- -
- - -
-
- - -
-
-
-
- -
-
-
- -
-
-
- - -
-
-
-
- -
-
-
- -
-
-
- - -
-
-
-
- -
-
-
- -
-
-
- - -
-
-
-
- -
- -
-
- - -
-
- - -
-
-
- -
- -
- Your app will be available in all territories and for free. If you want to change this please modify the app's settings in the app store. -
-
- - - -
- -
-
-
- - -
-
- diff --git a/backup/js/formValidation.js b/backup/js/formValidation.js deleted file mode 100644 index 501e83a..0000000 --- a/backup/js/formValidation.js +++ /dev/null @@ -1,38 +0,0 @@ - -var requiredList; - -function validateForm(platform, submissionType){ - - var hasError = false; - - requiredList = ['#appName', - '#appIconName', - '#shortdescription', - '#keywords', - '#primaryCategory', - '#description', - '#supportUrl', - '#copyright', - '#firstname', - '#lastname', - '#address', - '#city', - '#country', - '#postcode', - '#phonenumber', - '#email' - ]; - - $('.form-group').removeClass('has-error'); - - for (var input in requiredList){ - if (!$(requiredList[input]).closest( '.form-group' ).hasClass( 'hidden' )) { - if ( $(requiredList[input]).val() === '') { - $(requiredList[input]).closest( '.form-group' ).addClass( 'has-error' ); - hasError = true; - } - } - } - - return hasError; -} diff --git a/backup/js/interface.js b/backup/js/interface.js deleted file mode 100644 index 08c0675..0000000 --- a/backup/js/interface.js +++ /dev/null @@ -1,246 +0,0 @@ - -var $submissions = $('[data-submissions]'); -var $form = $('[data-submission]'); -var currentSubmission; -var submissionType; -var uploadedFiles = {}; - -$('input[type="file"]').each(function () { - $(this).parent().append([ - '', - '
    ' - ].join('')); -}); - -$('[data-create]').click(function (event) { - event.preventDefault(); - - hideForm(); - - Fliplet.App.Submissions.create({ - platform: prompt('Platform', 'ios') - }).then(function () { - loadSubmissions(); - }).catch(function (err) { - alert(err.responseJSON.message); - }); -}); - -$('[data-submissions]').change(function () { - var id = $(this).val(); - - hideForm(); - - if (!id) { - return; // you didn't select a submission - } - - Fliplet.App.Submissions.getById(id).then(function (submission) { - currentSubmission = submission; - fillForm(); - }); -}); - -$('input[type="file"]').change(function () { - var formData = new FormData(); - var files = this.files; - var $field = $(this); - var fieldName = $field.attr('name'); - var $message = $field.parent().find('.message'); - var currentFilesCount = $field.parent().find('.files li').length; - var max = parseInt($field.data('max') || 99); - - $message.removeClass('hidden'); - - if (currentFilesCount >= max) { - event.preventDefault(); - $message.text('You can only upload ' + max + ' files for this field.'); - return; - } - - for (var i = 0; i < files.length; i++) { - formData.append(fieldName, files.item(i)); - } - - $field.val(''); - $message.text('Uploading ' + (files.length+1) + ' files...'); - - Fliplet.Media.Files.upload({ - data: formData - }).then(function (files) { - $message.addClass('hidden'); - $message.text(''); - - files.forEach(function (file) { - addFile($field, file); - }); - }).catch(function (err) { - $message.html(err.message || err.description || err); - }); -}); - -function addFile($field, file) { - var $ul = $field.parent().find('.files'); - var $li = $([ - '
  • ', - '', - 'Delete', - '
  • ' - ].join('')); - - uploadedFiles[file.id] = file; - $ul.append($li); -} - -$('.files').on('click', '[data-delete]', function (event) { - event.preventDefault(); - var $li = $(this).parent(); - $li.remove(); - - Fliplet.Media.Files.delete($li.data('id')); -}); - -$('input[name=submissionType]').change(function(){ - //submissionType = this.value; - showForm(); -}); - -function hideForm() { - currentSubmission = undefined; - $form.addClass('hidden'); - $form[0].reset(); - $form.find('.files').html(''); -} - -function showForm() { - $form.removeClass('hidden'); - $form.find('.ios-only, .android-only, .windows-only, .appstore, .enterprise').addClass('hidden'); - - submissionType = $('input:radio[name=submissionType]:checked').val() - //alert($('input:radio[name=submissionType]').filter(":checked").val()); - - $(".appName-help-block").html("There is a limit of 50 characters, however we recommend keeping this to 23"); - $('input[name="appName"]').attr('maxlength', 50); - - if (currentSubmission.platform === "android"){ - $(".appName-help-block").html("There is a limit of 30 characters"); - $('input[name="appName"]').attr('maxlength', 30); - } - - $form.find('.' + currentSubmission.platform + '-only').removeClass('hidden'); - $form.find('.' + submissionType).removeClass('hidden'); -} - -function fillForm() { - _.forIn(currentSubmission.data, function (value, key) { - var $element = $form.find('[name="' + key + '"]'); - - if (key === 'submissionType' && value !== '') { - submissionType = value; - } - - if ($element.attr('type') === 'file') { - if (Array.isArray(value)) { - value.forEach(function (file) { - addFile($element, file); - }); - } else { - console.warn('Files for field ' + key + ' are expected to be an array.') - } - - return; - } - - if ($element.attr('type') === 'radio') { - $form.find('[name="' + key + '"][value="' + value + '"]').prop("checked", true); - return; - } - - $element.val(value); - }); - - $form.find('[data-save]').toggleClass('hidden', ['started', 'failed'].indexOf(currentSubmission.status) === -1); - $form.find('[data-build]').toggleClass('hidden', ['started', 'failed'].indexOf(currentSubmission.status) === -1); - - showForm(); -} - -function loadSubmissions() { - Fliplet.App.Submissions.get().then(function (submissions) { - $submissions.html(''); - - if (!submissions.length) { - return $submissions.append(''); - } - - $submissions.append(''); - - submissions.forEach(function (s) { - $submissions.append(''); - }); - }).catch(function (err) { - alert(err.responseJSON.message); - }); -} - -loadSubmissions(); - -$form.find('[data-build]').click(function (event) { - event.preventDefault(); - - if (validateForm(currentSubmission.platform, submissionType)){ - $('.has-errors:eq(0) input:eq(0)').focus() - return; - } - - saveForm().then(function () { - return Fliplet.App.Submissions.build(currentSubmission.id); - }).then(function () { - hideForm(); - loadSubmissions(); - }).catch(function (err) { - alert(err.responseJSON.message); - }); -}); - -function saveForm() { - var data = $form.serializeArray().reduce(function(obj, item) { - obj[item.name] = item.value; - return obj; - }, {}); - - $('input[type="file"]').each(function () { - var $el = $(this); - var $files = $el.parent().find('.files li'); - var filesList = []; - - $files.each(function () { - filesList.push(uploadedFiles[$(this).data('id')]); - }); - - data[$el.attr('name')] = filesList; - }); - - return Fliplet.App.Submissions.update(currentSubmission.id, data).catch(function (err) { - alert(err.responseJSON.message); - }); -} - -$form.submit(function (event) { - event.preventDefault(); - - if (validateForm(currentSubmission.platform, submissionType)){ - $('.has-errors:eq(0) input:eq(0)').focus(); - return; - } - - saveForm().then(function () { - hideForm(); - loadSubmissions(); - }); -}); - -// Fired from Fliplet Studio when the external save button is clicked -Fliplet.Widget.onSaveRequest(function () { - $form.submit(); -}); \ No newline at end of file diff --git a/backup/tests/index.js b/backup/tests/index.js deleted file mode 100644 index edcfc87..0000000 --- a/backup/tests/index.js +++ /dev/null @@ -1,69 +0,0 @@ -describe('WHEN start component', function() { - this.timeout(10000); - describe('Interface', function() { - it('should have empty username', function(done) { - interfaceBrowser - .evaluate(function (selector) { - return document.querySelector(selector).value; - }, '#username') - .then(function(username) { - expect(username).to.equal(''); - done(); - }) - }); - }); - - describe('Build', function() { - it('should have message to configure widget', function(done) { - const selector = `${buildSelector} h3`; - buildBrowser - .evaluate(function (selector) { - return document.querySelector(selector).textContent; - }, selector) - .then(function(message) { - expect(message).to.equal('This is the output of your widget'); - done(); - }); - }); - }); -}); - -describe('WHEN changing the username', function () { - this.timeout(10000); - const username = casual.username; - - before(function (done) { - interfaceBrowser - .type('#username') - .type('#username', username) - .save() // Use this method to save your widget instance - .then(done) - }); - - describe('Interface', function() { - it('should have new username on the input', function(done) { - interfaceBrowser - .evaluate(function (selector) { - return document.querySelector(selector).value; - }, '#username') - .then(function(inputUsername) { - expect(inputUsername).to.equal(username); - done(); - }) - }); - }); - - describe('Build', function() { - it('should have message with name', function(done) { - const selector = `${buildSelector} h2`; - buildBrowser - .evaluate(function (selector) { - return document.querySelector(selector).textContent; - }, selector) - .then(function(message) { - expect(message).to.equal(`Hi ${username}!`); - done(); - }); - }); - }); -}); diff --git a/backup/widget.json b/backup/widget.json deleted file mode 100644 index 17fe264..0000000 --- a/backup/widget.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "App Submissions", - "package": "com.fliplet.app-submissions", - "version": "1.0.0", - "icon": "img/icon.png", - "tags": [], - "provider_only": true, - "references": [], - "html_tag": "div", - "interface": { - "dependencies": [ - "lodash", - "fliplet-app-submissions", - "fliplet-media", - "fliplet-studio-ui", - "bootstrap" - ], - "assets": [ - "css/interface.css", - "js/formValidation.js", - "js/interface.js" - ] - }, - "build": { - "dependencies": [], - "assets": [] - } -} \ No newline at end of file From 76b1a289e96632f0118ffead3cb95a164cdc4b19 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Thu, 18 Oct 2018 18:15:26 +0100 Subject: [PATCH 073/318] Adds links to download p12 file after cert generation --- interface.html | 8 ++++---- js/interface.js | 8 ++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/interface.html b/interface.html index e3db7e4..a1986f6 100644 --- a/interface.html +++ b/interface.html @@ -632,7 +632,7 @@

    Apple developer account details and distribution certificates

    Distribution certificate created successfully.

    -

    Certificate Name - Expires on October 30th 2018

    +

    Certificate Name - Expires on (Download)

    @@ -647,7 +647,7 @@

    Apple developer account details and distribution certificates

    Distribution certificate created successfully.

    -

    Certificate Name - Expires on October 30th 2018

    +

    Certificate Name - Expires on (Download)

    @@ -1291,7 +1291,7 @@

    Apple developer account details and distribution certificates

    Distribution certificate created successfully.

    -

    Certificate Name - Expires on October 30th 2018

    +

    Certificate Name - Expires on (Download)

    @@ -1305,7 +1305,7 @@

    Apple developer account details and distribution certificates

    Distribution certificate created successfully.

    -

    Certificate Name - Expires on October 30th 2018

    +

    Certificate Name - Expires on (Download)

    diff --git a/js/interface.js b/js/interface.js index 0d6a74e..69655e0 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1962,9 +1962,11 @@ $('.appStore-generate-cert').on('click', function() { submissionId: appStoreSubmission.id }) .then(function(response) { + var p12Url = Fliplet.Env.get('apiUrl') + 'v1/organizations/' + organizationID + '/credentials/submission-' + appStoreSubmission.id + '/download/p12' appStoreCertificateCreated = true; $('.appStore-generate-file-success').find('.appStore-file-name-success').html(response.certificate.name); $('.appStore-generate-file-success').find('.appStore-file-expire-success').html(moment(response.certificate.expiresAt).format('MMMM Do YYYY')); + $('.appStore-generate-file-success').find('.appStore-file-download-success').attr('href', p12Url); $('.appStore-generate-file').removeClass('show'); $('.appStore-generate-file-success').addClass('show'); $this.html('Generate certificate'); @@ -2011,9 +2013,11 @@ $('.appStore-replace-cert').on('click', function() { submissionId: appStoreSubmission.id }) .then(function(response) { + var p12Url = Fliplet.Env.get('apiUrl') + 'v1/organizations/' + organizationID + '/credentials/submission-' + appStoreSubmission.id + '/download/p12' appStoreCertificateReplaced = true; $('.appStore-previous-file-success').find('.appStore-file-name-success').html(response.certificate.name); $('.appStore-previous-file-success').find('.appStore-file-expire-success').html(moment(response.certificate.expiresAt).format('MMMM Do YYYY')); + $('.appStore-previous-file-success').find('.appStore-file-download-success').attr('href', p12Url); $('.appStore-previous-file-success').addClass('show'); $this.html('Replace certificate'); $this.removeClass('disabled'); @@ -2172,9 +2176,11 @@ $('.enterprise-generate-cert').on('click', function() { inHouse: true }) .then(function(response) { + var p12Url = Fliplet.Env.get('apiUrl') + 'v1/organizations/' + organizationID + '/credentials/submission-' + enterpriseSubmission.id + '/download/p12' enterpriseCertificateCreated = true; $('.enterprise-generate-file-success').find('.enterprise-file-name-success').html(response.certificate.name); $('.enterprise-generate-file-success').find('.enterprise-file-expire-success').html(moment(response.certificate.expiresAt).format('MMMM Do YYYY')); + $('.enterprise-generate-file-success').find('.enterprise-file-download-success').attr('href', p12Url); $('.enterprise-generate-file').removeClass('show'); $('.enterprise-generate-file-success').addClass('show'); $this.html('Generate certificate'); @@ -2240,9 +2246,11 @@ $('.enterprise-replace-cert').on('click', function() { inHouse: true }) .then(function(response) { + var p12Url = Fliplet.Env.get('apiUrl') + 'v1/organizations/' + organizationID + '/credentials/submission-' + enterpriseSubmission.id + '/download/p12' enterpriseCertificateReplaced = true; $('.enterprise-previous-file-success').find('.enterprise-file-name-success').html(response.certificate.name); $('.enterprise-previous-file-success').find('.enterprise-file-expire-success').html(moment(response.certificate.expiresAt).format('MMMM Do YYYY')); + $('.enterprise-previous-file-success').find('.enterprise-file-download-success').attr('href', p12Url); $('.enterprise-previous-file-success').addClass('show'); $this.html('Replace certificate'); $this.removeClass('disabled'); From 69dbacb0cbcffbd91177e02b7521a906e485dcfd Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Tue, 23 Oct 2018 16:59:32 +0100 Subject: [PATCH 074/318] Stops making app store name readonly --- js/interface.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/js/interface.js b/js/interface.js index 69655e0..c20d425 100644 --- a/js/interface.js +++ b/js/interface.js @@ -96,9 +96,10 @@ function loadAppStoreData() { } $('[name="' + name + '"]').val(storeAppName); - if (!_.isUndefined($('[name="' + name + '"]').val()) && hasAppId) { - $('[name="' + name + '"]').attr('readonly', 'readonly'); - } + // Makes sure app store name is read-only if it's already provided + // if (!_.isUndefined($('[name="' + name + '"]').val()) && hasAppId) { + // $('[name="' + name + '"]').prop('readonly', true); + // } return; } From 582919aa40d64db4ac89ea3363654e421d53cea3 Mon Sep 17 00:00:00 2001 From: hcarneiro Date: Thu, 15 Nov 2018 15:50:57 +0000 Subject: [PATCH 075/318] Change to use settings overlay --- js/interface.js | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/js/interface.js b/js/interface.js index c20d425..9498c43 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1602,9 +1602,16 @@ $('[name="fl-store-keywords"]').on('tokenfield:createtoken', function(e) { $('.redirectToSettings, [data-change-settings]').on('click', function(event) { event.preventDefault(); - Fliplet.Studio.emit('navigate', { - name: 'appSettings', - params: { + Fliplet.Studio.emit('close-overlay', { + name: 'publish-apple' + }); + + Fliplet.Studio.emit('overlay', { + name: 'app-settings', + options: { + size: 'large', + title: 'App Settings', + section: 'appSettingsGeneral', appId: Fliplet.Env.get('appId') } }); @@ -1613,9 +1620,16 @@ $('.redirectToSettings, [data-change-settings]').on('click', function(event) { $('[data-change-assets]').on('click', function(event) { event.preventDefault(); - Fliplet.Studio.emit('navigate', { - name: 'launchAssets', - params: { + Fliplet.Studio.emit('close-overlay', { + name: 'publish-apple' + }); + + Fliplet.Studio.emit('overlay', { + name: 'app-settings', + options: { + size: 'large', + title: 'App Settings', + section: 'launchAssets', appId: Fliplet.Env.get('appId') } }); From e94ad43dc671ca742d5be67166f7c7d486de47ef Mon Sep 17 00:00:00 2001 From: hcarneiro Date: Tue, 20 Nov 2018 16:53:23 +0000 Subject: [PATCH 076/318] No ES6 for IE --- js/interface.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/js/interface.js b/js/interface.js index 9498c43..bf0de5d 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1101,13 +1101,13 @@ function cloneCredentials(organizationId, credentialKey, submission, saveData) { data: { key: submission.data['fl-credentials'] } - }).then(() => { + }).then(function() { if (saveData) { return Fliplet.App.Submissions.update(submission.id, submission.data); } return Promise.resolve(); - }).catch(() => { + }).catch(function() { //do nothing, a new credential will be created after the user logs in }); } @@ -1118,7 +1118,7 @@ function setCredentials(organizationId, id, data, verify = true) { url: 'v1/organizations/' + organizationId + '/credentials/submission-' + id + '?verify=' + verify, data: data }) - .then(() => { + .then(function() { return Promise.resolve(); }) } @@ -2363,7 +2363,7 @@ function publishApp(context) { method: 'POST', url: 'v1/apps/' + Fliplet.Env.get('appId') + '/publish', data: options - }).then((response) => { + }).then(function(response) { // Update appInfo appInfo.productionAppId = response.app.id; @@ -2760,7 +2760,7 @@ function initialLoad(initial, timeout) { return obj.platform === 'apple'; }); - return Promise.all(appleOnly.map((obj) => { + return Promise.all(appleOnly.map(function(obj) { return Fliplet.Media.Folders.get({folderId: obj.folderId}) .then(function(result) { var tempObject = { From 1c980c02a3a1fcf436439b409bc07bb51792ab23 Mon Sep 17 00:00:00 2001 From: hcarneiro Date: Tue, 20 Nov 2018 17:04:20 +0000 Subject: [PATCH 077/318] No ES6 defaults --- js/interface.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/interface.js b/js/interface.js index bf0de5d..26b5c0a 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1112,7 +1112,8 @@ function cloneCredentials(organizationId, credentialKey, submission, saveData) { }); } -function setCredentials(organizationId, id, data, verify = true) { +function setCredentials(organizationId, id, data, verify) { + verify = typeof verify === 'undefined' ? true : verify; return Fliplet.API.request({ method: 'PUT', url: 'v1/organizations/' + organizationId + '/credentials/submission-' + id + '?verify=' + verify, From 41d5bd49e4777bcb0b7d7323252d49c4c2fbb25b Mon Sep 17 00:00:00 2001 From: Nicholas Valbusa Date: Thu, 22 Nov 2018 18:46:36 +0100 Subject: [PATCH 078/318] check for undefined var --- js/interface.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/interface.js b/js/interface.js index 26b5c0a..ca88f0c 100644 --- a/js/interface.js +++ b/js/interface.js @@ -888,7 +888,7 @@ function saveAppStoreData(request) { if (name === 'fl-store-distribution') { var newValue = $('[name="'+name+'"]:checked').val(); - if (newValue === 'previous-file') { + if (newValue === 'previous-file' && appStorePreviousCredential) { pushData.apnTeamId = appStorePreviousCredential.teamId; } if (newValue === 'generate-file' || newValue === 'upload-file') { @@ -1767,7 +1767,7 @@ $('#enterpriseConfiguration').validator().on('submit', function(event) { return; } - saveEnterpriseData(true); + saveEnterpriseData(true); }); } else { Fliplet.Modal.alert({ From 42a4bb9ac76de281c4674bfde7ce0012b962976f Mon Sep 17 00:00:00 2001 From: Nicholas Valbusa Date: Thu, 22 Nov 2018 18:54:03 +0100 Subject: [PATCH 079/318] fixed null var --- js/interface.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/interface.js b/js/interface.js index ca88f0c..a059f4a 100644 --- a/js/interface.js +++ b/js/interface.js @@ -936,7 +936,7 @@ function saveEnterpriseData(request) { if (name === 'fl-ent-distribution') { var newValue = $('[name="'+name+'"]:checked').val(); - if (newValue === 'previous-file') { + if (newValue === 'previous-file' && enterprisePreviousCredential) { pushData.apnTeamId = enterprisePreviousCredential.teamId; } if (newValue === 'generate-file' || newValue === 'upload-file') { From 61e0769e29c7306860fb17cd6a62ea31dcbf7bbb Mon Sep 17 00:00:00 2001 From: Angel Nikolov Date: Thu, 3 Jan 2019 18:36:11 +0200 Subject: [PATCH 080/318] Disabled publish button upon save and enabled it back when the request finalizes --- js/interface.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/js/interface.js b/js/interface.js index a059f4a..a44cf97 100644 --- a/js/interface.js +++ b/js/interface.js @@ -548,6 +548,7 @@ function submissionBuild(appSubmission, origin) { Fliplet.Studio.emit('refresh-app-submissions'); $('.button-' + origin + '-request').html('Request App '); + $('.button-' + origin + '-request').prop('disabled', false); $('.save-' + origin + '-request').addClass('saved').hide().fadeIn(250); clearTimeout(initLoad); @@ -563,6 +564,7 @@ function submissionBuild(appSubmission, origin) { }, 10000); }, function(err) { $('.button-' + origin + '-request').html('Request App '); + $('.button-' + origin + '-request').prop('disabled', false); Fliplet.Modal.alert({ message: Fliplet.parseError(err) }); @@ -849,6 +851,7 @@ function requestBuild(origin, submission) { }) .catch(function(err) { $('.button-' + origin + '-request').html('Request App '); + $('.button-' + origin + '-request').prop('disabled', false); Fliplet.Modal.alert({ message: Fliplet.parseError(err) }); @@ -1710,6 +1713,7 @@ $('#appStoreConfiguration').validator().on('submit', function(event) { } } else { $('.button-appStore-request').html('Please wait '); + $('.button-appStore-request').prop('disabled', true); publishApp('appStore'); } @@ -1776,6 +1780,7 @@ $('#enterpriseConfiguration').validator().on('submit', function(event) { } } else { $('.button-enterprise-request').html('Please wait '); + $('.button-enterprise-request').prop('disabled', true); publishApp('enterprise'); } @@ -1819,6 +1824,7 @@ $('#unsignedConfiguration').validator().on('submit', function(event) { } } else { $('.button-unsigned-request').html('Please wait '); + $('.button-unsigned-request').prop('disabled', true); publishApp('unsigned'); } @@ -2371,14 +2377,17 @@ function publishApp(context) { switch(context) { case 'appStore': $('.button-appStore-request').html('Request App '); + $('.button-appStore-request').prop('disabled', false); $('#appStoreConfiguration').validator().trigger('submit'); break; case 'enterprise': $('.button-enterprise-request').html('Request App '); + $('.button-enterprise-request').prop('disabled', false); $('#enterpriseConfiguration').validator().trigger('submit'); break; case 'unsigned': $('.button-unsigned-request').html('Request App '); + $('.button-unsigned-request').prop('disabled', false); $('#unsignedConfiguration').validator().trigger('submit'); break; default: From dfd87d787a99b446bc323859f892e8789b98c74b Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Wed, 30 Jan 2019 10:29:34 +0000 Subject: [PATCH 081/318] Removes duplicated words --- interface.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface.html b/interface.html index a1986f6..ab160a1 100644 --- a/interface.html +++ b/interface.html @@ -1181,7 +1181,7 @@

    Apple developer account details and distribution certificates

    -

    Warning! This area should only be used if you have technical technical knowledge on enterprise app submissions, p12 files and mobile provisioning files.

    +

    Warning! This area should only be used if you have technical knowledge on enterprise app submissions, p12 files and mobile provisioning files.

    From 2b2aaf43e3ae11a41614c5654ed45a7b59bff3cc Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Wed, 30 Jan 2019 10:29:39 +0000 Subject: [PATCH 082/318] Spacing --- interface.html | 56 +++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/interface.html b/interface.html index ab160a1..c6375c6 100644 --- a/interface.html +++ b/interface.html @@ -41,11 +41,11 @@
    @@ -256,37 +256,37 @@
    @@ -1615,15 +1615,15 @@

    App submission status

    \{{/if}} \{{#if failed}} -
    Failed
    +
    Failed
    \{{#if updatedAt}} Finished on: \{{updatedAt}}\{{/if}} - \{{#if message}} + \{{#if message}}
    \{{message}}
    \{{else}}
    There was an error building your app
    - \{{/if}} + \{{/if}} \{{/if}} \{{#if cancelled}} From 6fa74af258a74c912ecce44de803c68e9091af9c Mon Sep 17 00:00:00 2001 From: Nicholas Valbusa Date: Mon, 11 Feb 2019 15:40:13 +0100 Subject: [PATCH 083/318] fixes for manual submissions --- js/interface.js | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/js/interface.js b/js/interface.js index a44cf97..5d1d0b9 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1003,6 +1003,8 @@ function saveEnterpriseData(request) { enterpriseSubmission.data = data; notificationSettings = pushData; + delete enterpriseSubmission.data['fl-credentials']; + savePushData(true); if (request) { @@ -1742,18 +1744,20 @@ $('#enterpriseConfiguration').validator().on('submit', function(event) { var credentialKind = $('[name="fl-ent-distribution"]:checked').val(); - if (credentialKind === 'generate-file' && !enterpriseCertificateCreated) { - Fliplet.Modal.alert({ - message: 'You need to generate a certificate before requesting a submission' - }); - return; - } + if (!enterpriseManual) { + if (credentialKind === 'generate-file' && !enterpriseCertificateCreated) { + Fliplet.Modal.alert({ + message: 'You need to generate a certificate before requesting a submission' + }); + return; + } - if (credentialKind === 'upload-file' && (!enterpriseFileField.files || !enterpriseFileField.files[0])) { - Fliplet.Modal.alert({ - message: 'You need to upload a certificate before requesting a submission' - }); - return; + if (credentialKind === 'upload-file' && (!enterpriseFileField.files || !enterpriseFileField.files[0])) { + Fliplet.Modal.alert({ + message: 'You need to upload a certificate before requesting a submission' + }); + return; + } } if (appInfo && appInfo.productionAppId) { @@ -2472,10 +2476,10 @@ function checkSubmissionStatus(origin, iosSubmissions) { build.id = submission.id; build.updatedAt = ((submission.status === 'completed' || submission.status === 'failed' || submission.status === 'cancelled' || submission.status === 'ready-for-testing' || submission.status === 'tested') && submission.updatedAt) ? - moment(submission.updatedAt).format('MMM Do YYYY, h:mm:ss a') : + moment(submission.updatedAt).format('MMM Do YYYY, HH:mm') : ''; build.submittedAt = ((submission.status === 'queued' || submission.status === 'submitted') && submission.submittedAt) ? - moment(submission.submittedAt).format('MMM Do YYYY, h:mm:ss a') : + moment(submission.submittedAt).format('MMM Do YYYY, HH:mm') : ''; build[submission.status] = true; build.fileUrl = appBuild ? appBuild.url : ''; From b9529e735c1ae5c90b58b2098fbd73f81d30b67d Mon Sep 17 00:00:00 2001 From: Nicholas Valbusa Date: Mon, 11 Feb 2019 15:44:52 +0100 Subject: [PATCH 084/318] reverted date format --- js/interface.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/interface.js b/js/interface.js index 5d1d0b9..a27df01 100644 --- a/js/interface.js +++ b/js/interface.js @@ -2476,10 +2476,10 @@ function checkSubmissionStatus(origin, iosSubmissions) { build.id = submission.id; build.updatedAt = ((submission.status === 'completed' || submission.status === 'failed' || submission.status === 'cancelled' || submission.status === 'ready-for-testing' || submission.status === 'tested') && submission.updatedAt) ? - moment(submission.updatedAt).format('MMM Do YYYY, HH:mm') : + moment(submission.updatedAt).format('MMM Do YYYY, h:mm:ss a') : ''; build.submittedAt = ((submission.status === 'queued' || submission.status === 'submitted') && submission.submittedAt) ? - moment(submission.submittedAt).format('MMM Do YYYY, HH:mm') : + moment(submission.submittedAt).format('MMM Do YYYY, h:mm:ss a') : ''; build[submission.status] = true; build.fileUrl = appBuild ? appBuild.url : ''; From ed50141f28ed9bbf6e79d34a686cfaea179187e3 Mon Sep 17 00:00:00 2001 From: Nicholas Valbusa Date: Wed, 13 Feb 2019 17:45:46 +0100 Subject: [PATCH 085/318] copy for when debug link is not available --- interface.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface.html b/interface.html index c6375c6..7dea706 100644 --- a/interface.html +++ b/interface.html @@ -1584,7 +1584,7 @@

    App submission status

    \{{#if fileUrl}} \{{/if}} \{{#if debugFileUrl}} - \{{/if}} + \{{else}}
    Debug app not available
    \{{/if}} \{{#if updatedAt}} Finished on: \{{updatedAt}}\{{/if}} @@ -1597,7 +1597,7 @@

    App submission status

    \{{#if fileUrl}} \{{/if}} \{{#if debugFileUrl}} - \{{/if}} + \{{else}}
    Debug app not available
    \{{/if}} \{{#if updatedAt}} Ready on: \{{updatedAt}}\{{/if}} From 51683256989eb724fe448026332f83da5f612ed6 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Fri, 15 Feb 2019 11:45:39 +0000 Subject: [PATCH 086/318] Fixes typo in selector --- js/interface.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/interface.js b/js/interface.js index a27df01..cde0bf1 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1588,7 +1588,7 @@ $('.panel-group').on('shown.bs.collapse', '.panel-collapse', function() { Fliplet.Widget.autosize(); }); -$('a[data-toggle="tab"').on('shown.bs.tab', function() { +$('a[data-toggle="tab"]').on('shown.bs.tab', function() { Fliplet.Widget.autosize(); }) .on('hidden.bs.tab', function() { From 17976bea3d921812a9f6eef6fe779bb0171e83cd Mon Sep 17 00:00:00 2001 From: Nicholas Valbusa Date: Tue, 19 Feb 2019 13:56:00 +0100 Subject: [PATCH 087/318] support for 2FA code when requested --- js/interface.js | 12 +++++++++++- widget.json | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/js/interface.js b/js/interface.js index cde0bf1..3972556 100644 --- a/js/interface.js +++ b/js/interface.js @@ -40,6 +40,7 @@ var screenShotsMobile = []; var screenShotsTablet = []; var haveScreenshots = false; var screenshotValidationNotRequired = false; +var socket = Fliplet.Socket({ login: true }); /* FUNCTIONS */ String.prototype.toCamelCase = function() { @@ -2821,4 +2822,13 @@ function initialLoad(initial, timeout) { } // Start -initLoad = initialLoad(true, 0); \ No newline at end of file +initLoad = initialLoad(true, 0); + +// Listen for 2FA code when requested +socket.on('aab.apple.login.2fa', function (data) { + // Ask user for code + var code = prompt('Please type the 2FA code to log in'); + + // Notify requester with the code + socket.to(data.clientId).emit('aab.apple.login.2fa.code', code); +}); \ No newline at end of file diff --git a/widget.json b/widget.json index 5449251..79b96ad 100644 --- a/widget.json +++ b/widget.json @@ -12,6 +12,7 @@ "lodash", "fliplet-app-submissions", "fliplet-media", + "fliplet-socket", "fliplet-studio-ui", "handlebars", "bootstrap", From a05c9b10863db6e7e50f2116adaa1b3271a97bd6 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Tue, 19 Feb 2019 17:51:56 +0000 Subject: [PATCH 088/318] Updates prompt to use Fliplet.Modal --- js/interface.js | 34 +++++++++++++++++++++++++++++++--- js/interface.templates.js | 4 ++-- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/js/interface.js b/js/interface.js index 3972556..b1e6b3f 100644 --- a/js/interface.js +++ b/js/interface.js @@ -2824,11 +2824,39 @@ function initialLoad(initial, timeout) { // Start initLoad = initialLoad(true, 0); +// @TODO Move function +function prompt2FACode() { + // @TODO Update Fliplet.Modal in fliplet-api for simpler call + return Fliplet.Modal.prompt({ + title: 'Please enter the verification code to verify your login' + }).then(function (code) { + if (code === null) { + return null; + } + + if (code === '') { + return Fliplet.Modal.alert({ + message: 'You must enter the verifiaction code to log in' + }).then(function () { + return prompt2FACode(); + }); + } + + return code; + }); +} + // Listen for 2FA code when requested socket.on('aab.apple.login.2fa', function (data) { // Ask user for code - var code = prompt('Please type the 2FA code to log in'); + prompt2FACode().then(function (code) { + if (code === null) { + // @TODO Cancels login + return; + } - // Notify requester with the code - socket.to(data.clientId).emit('aab.apple.login.2fa.code', code); + // Notify requester with the code + // @Question What happens when 2FA fails? + socket.to(data.clientId).emit('aab.apple.login.2fa.code', code); + }); }); \ No newline at end of file diff --git a/js/interface.templates.js b/js/interface.templates.js index 8167d6d..059f4f5 100644 --- a/js/interface.templates.js +++ b/js/interface.templates.js @@ -5,7 +5,7 @@ this["Fliplet"]["Widget"]["Templates"] = this["Fliplet"]["Widget"]["Templates"] this["Fliplet"]["Widget"]["Templates"]["templates.thumbs"] = Handlebars.template({"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { var helper; - return "
    \r\n \n \r\n
    "; + + "\"/>\n"; },"useData":true}); \ No newline at end of file From 6a9c4c48049d8d469594ce10e23ae6f4825bd9a7 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Tue, 19 Feb 2019 23:55:54 +0000 Subject: [PATCH 089/318] Comment update --- js/interface.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/interface.js b/js/interface.js index b1e6b3f..747e1ec 100644 --- a/js/interface.js +++ b/js/interface.js @@ -2856,7 +2856,7 @@ socket.on('aab.apple.login.2fa', function (data) { } // Notify requester with the code - // @Question What happens when 2FA fails? + // @Question What happens when 2FA succeeds/fails? socket.to(data.clientId).emit('aab.apple.login.2fa.code', code); }); }); \ No newline at end of file From 94c81046e522b79e6566131873c2830792e0163d Mon Sep 17 00:00:00 2001 From: Nicholas Valbusa Date: Wed, 20 Feb 2019 12:01:06 +0100 Subject: [PATCH 090/318] events for code failure and success --- js/interface.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/js/interface.js b/js/interface.js index 747e1ec..ccd8497 100644 --- a/js/interface.js +++ b/js/interface.js @@ -2859,4 +2859,14 @@ socket.on('aab.apple.login.2fa', function (data) { // @Question What happens when 2FA succeeds/fails? socket.to(data.clientId).emit('aab.apple.login.2fa.code', code); }); +}); + +// Listen for a 2FA code successfully entered +socket.on('aab.apple.login.2fa.success', function () { + console.log('2FA code is correct'); +}); + +// Listen for a wrong 2FA code +socket.on('aab.apple.login.2fa.failure', function () { + console.log('2FA code is wrong'); }); \ No newline at end of file From 64ff037ecb8f91d34c31b01af77c90de4d404093 Mon Sep 17 00:00:00 2001 From: Nicholas Valbusa Date: Wed, 20 Feb 2019 12:02:21 +0100 Subject: [PATCH 091/318] event for when 2fa login is canceled --- js/interface.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/interface.js b/js/interface.js index ccd8497..0fd0053 100644 --- a/js/interface.js +++ b/js/interface.js @@ -2851,7 +2851,7 @@ socket.on('aab.apple.login.2fa', function (data) { // Ask user for code prompt2FACode().then(function (code) { if (code === null) { - // @TODO Cancels login + socket.to(data.clientId).emit('aab.apple.login.2fa.cancel', code); return; } From 9dcc6ce13413372c285e86218d35cfee44a1aa12 Mon Sep 17 00:00:00 2001 From: Nicholas Valbusa Date: Wed, 20 Feb 2019 12:04:31 +0100 Subject: [PATCH 092/318] tweak --- js/interface.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/interface.js b/js/interface.js index 0fd0053..00fec9f 100644 --- a/js/interface.js +++ b/js/interface.js @@ -2851,7 +2851,7 @@ socket.on('aab.apple.login.2fa', function (data) { // Ask user for code prompt2FACode().then(function (code) { if (code === null) { - socket.to(data.clientId).emit('aab.apple.login.2fa.cancel', code); + socket.to(data.clientId).emit('aab.apple.login.2fa.cancel'); return; } From 6a2433709a64aece4f1f0d0b502ce75b863e05f4 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Wed, 20 Feb 2019 11:05:53 +0000 Subject: [PATCH 093/318] Typo --- js/interface.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/interface.js b/js/interface.js index 00fec9f..db7abd4 100644 --- a/js/interface.js +++ b/js/interface.js @@ -2836,7 +2836,7 @@ function prompt2FACode() { if (code === '') { return Fliplet.Modal.alert({ - message: 'You must enter the verifiaction code to log in' + message: 'You must enter the verification code to log in' }).then(function () { return prompt2FACode(); }); From 08352d661a4d5f62cdc0a7f46b9b2dd5d46fcc26 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Wed, 20 Feb 2019 11:11:25 +0000 Subject: [PATCH 094/318] Moving all functions together --- js/interface.js | 2242 +++++++++++++++++++++++------------------------ 1 file changed, 1121 insertions(+), 1121 deletions(-) diff --git a/js/interface.js b/js/interface.js index db7abd4..32aad57 100644 --- a/js/interface.js +++ b/js/interface.js @@ -50,12 +50,12 @@ String.prototype.toCamelCase = function() { }).replace(/([^A-Z-a-z])/g, '').toLowerCase(); }; -var createBundleID = function(orgName, appName) { +function createBundleID(orgName, appName) { return $.ajax({ url: "https://itunes.apple.com/lookup?bundleId=com." + orgName + "." + appName, dataType: "jsonp" }); -}; +} function incrementVersionNumber(versionNumber) { var splitNumber = versionNumber.split('.'); @@ -1510,1341 +1510,1341 @@ function validateScreenshots() { return true; } -/* ATTACH LISTENERS */ -$('[name="fl-store-screenshots"]').on('change', function() { - var value = $(this).val(); - var id = $(this).attr('id'); - checkHasScreenshots(); +function publishApp(context) { + var options = { + release: { + type: 'silent', + changelog: 'Initial version' + } + }; + Fliplet.API.request({ + method: 'POST', + url: 'v1/apps/' + Fliplet.Env.get('appId') + '/publish', + data: options + }).then(function(response) { + // Update appInfo + appInfo.productionAppId = response.app.id; - if (value === 'new' && !haveScreenshots) { - $('[data-item="fl-store-screenshots-new-warning"]').addClass('show'); + switch(context) { + case 'appStore': + $('.button-appStore-request').html('Request App '); + $('.button-appStore-request').prop('disabled', false); + $('#appStoreConfiguration').validator().trigger('submit'); + break; + case 'enterprise': + $('.button-enterprise-request').html('Request App '); + $('.button-enterprise-request').prop('disabled', false); + $('#enterpriseConfiguration').validator().trigger('submit'); + break; + case 'unsigned': + $('.button-unsigned-request').html('Request App '); + $('.button-unsigned-request').prop('disabled', false); + $('#unsignedConfiguration').validator().trigger('submit'); + break; + default: + break; + } + }); +} - $('[data-item="fl-store-screenshots-new"]').removeClass('show'); - $('[data-item="fl-store-screenshots-existing"]').removeClass('show'); +function compileStatusTable(withData, origin, buildsData) { + if (withData) { + var template = Handlebars.compile(statusTableTemplate); + var html = template(buildsData); + + if (origin === "appStore") { + $statusAppStoreTableElement.html(html); + } + if (origin === "enterprise") { + $statusEnterpriseTableElement.html(html); + } + if (origin === "unsigned") { + $statusUnsignedTableElement.html(html); + } + } else { + if (origin === "appStore") { + $statusAppStoreTableElement.html(''); + } + if (origin === "enterprise") { + $statusEnterpriseTableElement.html(''); + } + if (origin === "unsigned") { + $statusUnsignedTableElement.html(''); + } } - if (value === 'new' && haveScreenshots) { - $('[data-item="fl-store-screenshots-new-warning"]').removeClass('show'); - $('[data-item="fl-store-screenshots-new"]').addClass('show'); - $('[data-item="fl-store-screenshots-existing"]').removeClass('show'); + Fliplet.Widget.autosize(); +} +function checkSubmissionStatus(origin, iosSubmissions) { + var submissionsToShow = _.filter(iosSubmissions, function(submission) { + return submission.status === "queued" || submission.status === "submitted" || submission.status === "processing" || submission.status === "completed" || submission.status === "failed" || submission.status === "cancelled" || submission.status === "ready-for-testing" || submission.status === "tested"; + }); - _.take(screenShotsMobile, 4).forEach(function(thumb) { - $('.mobile-thumbs').append(addThumb(thumb)); - }); + var buildsData = []; + if (submissionsToShow.length) { + submissionsToShow.forEach(function(submission) { + var build = {}; + var appBuild; + var debugHtmlPage; - _.take(screenShotsTablet, 4).forEach(function(thumb) { - $('.tablet-thumbs').append(addThumb(thumb)); - }); - } - if (value === 'existing') { - $('.app-details-appStore .app-screenshots').removeClass('has-error'); - $('[data-item="fl-store-screenshots-existing"]').addClass('show'); + // Default copy for testing status for different users + if (submission.status === 'ready-for-testing') { + if (userInfo.user && (userInfo.user.isAdmin || userInfo.user.isImpersonating)) { + // Fliplet users + build.testingStatus = 'Ready for testing'; + build.testingMessage = 'App is ready for testing'; + } else { + // Normal users + build.testingStatus = 'In testing'; + build.testingMessage = 'Your app is being tested by Fliplet'; + } + } - $('[data-item="fl-store-screenshots-new-warning"]').removeClass('show'); - $('[data-item="fl-store-screenshots-new"]').removeClass('show'); - } -}); + if (submission.result.appBuild && submission.result.appBuild.files) { + appBuild = _.find(submission.result.appBuild.files, function(file) { + return file.contentType === 'application/octet-stream'; + }); + } else if (submission.data.previousResults && submission.data.previousResults.appBuild && submission.data.previousResults.appBuild.files) { + appBuild = _.find(submission.data.previousResults.appBuild.files, function(file) { + return file.contentType === 'application/octet-stream'; + }); + } -$('[name="submissionType"]').on('change', function() { - var selectedOptionId = $(this).attr('id'); + if (submission.result.debugHtmlPage && submission.result.debugHtmlPage.files) { + debugHtmlPage = _.find(submission.result.debugHtmlPage.files, function(file) { + return file.contentType === 'text/html'; + }); + } else if (submission.data.previousResults && submission.data.previousResults.debugHtmlPage && submission.data.previousResults.debugHtmlPage.files) { + debugHtmlPage = _.find(submission.data.previousResults.debugHtmlPage.files, function(file) { + return file.contentType === 'text/html'; + }); + } - $('.fl-sb-panel').removeClass('show'); - $('.' + selectedOptionId).addClass('show'); + build.id = submission.id; + build.updatedAt = ((submission.status === 'completed' || submission.status === 'failed' || submission.status === 'cancelled' || submission.status === 'ready-for-testing' || submission.status === 'tested') && submission.updatedAt) ? + moment(submission.updatedAt).format('MMM Do YYYY, h:mm:ss a') : + ''; + build.submittedAt = ((submission.status === 'queued' || submission.status === 'submitted') && submission.submittedAt) ? + moment(submission.submittedAt).format('MMM Do YYYY, h:mm:ss a') : + ''; + build[submission.status] = true; + build.fileUrl = appBuild ? appBuild.url : ''; - Fliplet.Widget.autosize(); -}); + if (submission.result.message) { + build.message = submission.result.message; + } -$('[name="fl-store-credentials"]').on('change', function() { - var value = $(this).val(); + if (userInfo.user && (userInfo.user.isAdmin || userInfo.user.isImpersonating)) { + build.debugFileUrl = debugHtmlPage ? debugHtmlPage.url : ''; + } - if (value === 'useOwn') { - $('.fl-store-credential.indented-area').removeClass('hidden'); + buildsData.push(build); + }); + + compileStatusTable(true, origin, buildsData); } else { - $('.fl-store-credential.indented-area').addClass('hidden'); + compileStatusTable(false, origin); } +} - Fliplet.Widget.autosize(); -}); - -$('.fl-sb-appStore [change-bundleid], .fl-sb-enterprise [change-bundleid], .fl-sb-unsigned [change-bundleid]').on('click', function() { - Fliplet.Modal.confirm({ - message: 'Are you sure you want to change the unique Bundle ID?' - }).then(function (confirmed) { - if (!confirmed) { - return; - } - - $('.fl-bundleId-holder').addClass('hidden'); - $('.fl-bundleId-field').addClass('show'); - - Fliplet.Widget.autosize(); +function submissionChecker(submissions) { + var asub = _.filter(submissions, function(submission) { + return submission.data.submissionType === "appStore" && submission.platform === "ios"; }); -}); -$('.panel-group').on('shown.bs.collapse', '.panel-collapse', function() { - Fliplet.Widget.autosize(); - }) - .on('hidden.bs.collapse', '.panel-collapse', function() { - Fliplet.Widget.autosize(); + var completedAsub = _.filter(asub, function(submission) { + return submission.status === "completed"; }); -$('a[data-toggle="tab"]').on('shown.bs.tab', function() { - Fliplet.Widget.autosize(); - }) - .on('hidden.bs.tab', function() { - Fliplet.Widget.autosize(); + //Get the Submission data from the first completed submission, it has the certification values that are in use on the app store. + previousAppStoreSubmission = _.minBy(completedAsub, function(el) { + return el.id; }); -$('[name="fl-store-keywords"]').on('tokenfield:createtoken', function(e) { - var currentValue = e.currentTarget.value.replace(/,\s+/g, ','); - var newValue = e.attrs.value; - var oldAndNew = currentValue + ',' + newValue; + appStoreSubmissionInStore = (completedAsub.length > 0); - if (oldAndNew.length > 100) { - e.preventDefault(); + asub = _.orderBy(asub, function(submission) { + return new Date(submission.createdAt).getTime(); + }, ['desc']); + checkSubmissionStatus("appStore", asub); + + appStoreSubmission = _.maxBy(asub, function(el) { + return new Date(el.createdAt).getTime(); + }); + + if (!appStoreSubmission) { + appStoreSubmission = {}; } -}); -$('.redirectToSettings, [data-change-settings]').on('click', function(event) { - event.preventDefault(); + var cloneAppStoreCredentialsPromise = Promise.resolve(); + if (appStoreSubmission.data && !appStoreSubmission.data['fl-credentials']) { - Fliplet.Studio.emit('close-overlay', { - name: 'publish-apple' - }); + var prevSubCred = _.filter(asub, function(submission) { + return submission.data && submission.data['fl-credentials']; + }); - Fliplet.Studio.emit('overlay', { - name: 'app-settings', - options: { - size: 'large', - title: 'App Settings', - section: 'appSettingsGeneral', - appId: Fliplet.Env.get('appId') + var previousSubWithCredentials = _.maxBy(prevSubCred, function(el) { + return new Date(el.createdAt).getTime(); + }); + + appStoreSubmission.data['fl-credentials'] = 'submission-' + appStoreSubmission.id; + + if(previousSubWithCredentials) { + cloneAppStoreCredentialsPromise = cloneCredentials(organizationID, previousSubWithCredentials.data['fl-credentials'], appStoreSubmission, true); } - }); -}); + } -$('[data-change-assets]').on('click', function(event) { - event.preventDefault(); + var esub = _.filter(submissions, function(submission) { + return submission.data.submissionType === "enterprise" && submission.platform === "ios"; + }); - Fliplet.Studio.emit('close-overlay', { - name: 'publish-apple' + var completedEsub = _.filter(esub, function(submission) { + return submission.status === "completed"; + }); + //Get the Submission data from the first completed submission, it has certification values that are in use on the developer portal. + previousEnterpriseStoreSubmission = _.minBy(completedEsub, function(el) { + return el.id; }); - Fliplet.Studio.emit('overlay', { - name: 'app-settings', - options: { - size: 'large', - title: 'App Settings', - section: 'launchAssets', - appId: Fliplet.Env.get('appId') - } - }); -}); + esub = _.orderBy(esub, function(submission) { + return new Date(submission.createdAt).getTime(); + }, ['desc']); + checkSubmissionStatus("enterprise", esub); -$('#appStoreConfiguration, #enterpriseConfiguration, #unsignedConfiguration').on('validated.bs.validator', function() { - checkGroupErrors(); - Fliplet.Widget.autosize(); -}); + enterpriseSubmission = _.maxBy(esub, function(el) { + return new Date(el.createdAt).getTime(); + }); -$('#appStoreConfiguration').validator().on('submit', function(event) { - if (event.isDefaultPrevented()) { - // Gives time to Validator to apply classes - setTimeout(checkGroupErrors, 0); - Fliplet.Modal.alert({ - message: 'Please fill in all the required information.' - }); - return; + if (!enterpriseSubmission) { + enterpriseSubmission = {}; } - event.preventDefault(); + var cloneEnterpriseCredentialsPromise = Promise.resolve(); + if (enterpriseSubmission.data && !enterpriseSubmission.data['fl-credentials']) { - if ($('[name="fl-store-screenshots"]:checked').val() === 'new' && !haveScreenshots) { - Fliplet.Modal.alert({ - message: 'You need to add screenshots before submitting' + var prevSubCred = _.filter(esub, function(submission) { + return submission.data && submission.data['fl-credentials']; }); - return; - } - - if (!validateScreenshots()) { - return; - } - - if (appInfo && appInfo.productionAppId) { - if (allAppData.indexOf('appStore') > -1) { - if (appStoreLoggedIn) { - var certificateKind = $('[name="fl-store-distribution"]:checked').val(); - - if (certificateKind === 'generate-file' && !appStoreCertificateCreated) { - Fliplet.Modal.alert({ - message: 'You need to generate a certificate before requesting a submission' - }); - return; - } - - if (certificateKind === 'upload-file' && (!appStoreFileField.files || !appStoreFileField.files[0])){ - Fliplet.Modal.alert({ - message: 'You need to upload a certificate before requesting a submission' - }); - return; - } - - var message = 'Are you sure you wish to update your published app?'; - if (appStoreSubmission.status === "started") { - message = 'Are you sure you wish to request your app to be published?'; - } + var previousSubWithCredentials = _.maxBy(prevSubCred, function(el) { + return new Date(el.createdAt).getTime(); + }); - Fliplet.Modal.confirm({ - message: message - }).then(function (confirmed) { - if (!confirmed) { - return; - } + enterpriseSubmission.data['fl-credentials'] = 'submission-' + enterpriseSubmission.id; - saveAppStoreData(true); - }); - } else { - Fliplet.Modal.alert({ - message: 'You need to login with your Apple developer account details.
    Select one option to provide use with a distribution certificate.' - }); - } - } else { - Fliplet.Modal.alert({ - message: 'Please configure your App Settings to contain the required information.' - }); + if(previousSubWithCredentials) { + cloneEnterpriseCredentialsPromise = cloneCredentials(organizationID, previousSubWithCredentials.data['fl-credentials'], enterpriseSubmission, true); } - } else { - $('.button-appStore-request').html('Please wait '); - $('.button-appStore-request').prop('disabled', true); - publishApp('appStore'); - } - - // Gives time to Validator to apply classes - setTimeout(checkGroupErrors, 0); -}); - -$('#enterpriseConfiguration').validator().on('submit', function(event) { - if (event.isDefaultPrevented()) { - // Gives time to Validator to apply classes - setTimeout(checkGroupErrors, 0); - Fliplet.Modal.alert({ - message: 'Please fill in all the required information.' - }); - return; } - event.preventDefault(); + var usub = _.filter(submissions, function(submission) { + return submission.data.submissionType === "unsigned" && submission.platform === "ios"; + }); - if (!enterpriseManual && !enterpriseLoggedIn) { - Fliplet.Modal.alert({ - message: 'Please log in with the Apple Developer Account or choose to enter the data manually.' - }); - return; - } + usub = _.orderBy(usub, function(submission) { + return new Date(submission.createdAt).getTime(); + }, ['desc']); + checkSubmissionStatus("unsigned", usub); - var credentialKind = $('[name="fl-ent-distribution"]:checked').val(); + usub = _.maxBy(usub, function(el) { + return new Date(el.createdAt).getTime(); + }); + unsignedSubmission = usub; - if (!enterpriseManual) { - if (credentialKind === 'generate-file' && !enterpriseCertificateCreated) { - Fliplet.Modal.alert({ - message: 'You need to generate a certificate before requesting a submission' + return cloneAppStoreCredentialsPromise.then(function () { + return cloneEnterpriseCredentialsPromise; + }).then(function () { + if (_.isEmpty(appStoreSubmission)) { + return Fliplet.App.Submissions.create({ + platform: 'ios', + data: { + submissionType: "appStore" + } + }) + .then(function(submission) { + appStoreSubmission = submission; + return Promise.resolve(); }); - return; } - if (credentialKind === 'upload-file' && (!enterpriseFileField.files || !enterpriseFileField.files[0])) { - Fliplet.Modal.alert({ - message: 'You need to upload a certificate before requesting a submission' + return Promise.resolve(); + }).then(function () { + if (_.isEmpty(enterpriseSubmission)) { + return Fliplet.App.Submissions.create({ + platform: 'ios', + data: { + submissionType: "enterprise" + } + }) + .then(function(submission) { + enterpriseSubmission = submission; + return Promise.resolve(); }); - return; } - } - - if (appInfo && appInfo.productionAppId) { - if (allAppData.indexOf('enterprise') > -1) { - var message = 'Are you sure you wish to update your published app?'; - - if (enterpriseSubmission.status === "started") { - message = 'Are you sure you wish to request your app to be published?'; - } - Fliplet.Modal.confirm({ - message: message - }).then(function (confirmed) { - if (!confirmed) { - return; + return Promise.resolve(); + }).then(function () { + if (_.isEmpty(unsignedSubmission)) { + return Fliplet.App.Submissions.create({ + platform: 'ios', + data: { + submissionType: "unsigned" } - - saveEnterpriseData(true); - }); - } else { - Fliplet.Modal.alert({ - message: 'Please configure your App Settings to contain the required information.' + }) + .then(function(submission) { + unsignedSubmission = submission; + return Promise.resolve(); }); } - } else { - $('.button-enterprise-request').html('Please wait '); - $('.button-enterprise-request').prop('disabled', true); - publishApp('enterprise'); - } - // Gives time to Validator to apply classes - setTimeout(checkGroupErrors, 0); -}); + return Promise.resolve(); + }); +} -$('#unsignedConfiguration').validator().on('submit', function(event) { - if (event.isDefaultPrevented()) { - // Gives time to Validator to apply classes - setTimeout(checkGroupErrors, 0); - Fliplet.Modal.alert({ - message: 'Please fill in all the required information.' - }); - return; - } +function iosSubmissionChecker(submissions) { + var asub = _.filter(submissions, function(submission) { + return submission.data.submissionType === "appStore" && submission.platform === "ios"; + }); - event.preventDefault(); + var esub = _.filter(submissions, function(submission) { + return submission.data.submissionType === "enterprise" && submission.platform === "ios"; + }); - if (appInfo && appInfo.productionAppId) { - if (allAppData.indexOf('unsigned') > -1) { - var message = 'Are you sure you wish to update your published app?'; + var usub = _.filter(submissions, function(submission) { + return submission.data.submissionType === "unsigned" && submission.platform === "ios"; + }); - if (unsignedSubmission.status === "started") { - message = 'Are you sure you wish to request your app to be published?'; - } + // Ordering + asub = _.orderBy(asub, function(submission) { + return new Date(submission.createdAt).getTime(); + }, ['desc']); + esub = _.orderBy(esub, function(submission) { + return new Date(submission.createdAt).getTime(); + }, ['desc']); + usub = _.orderBy(usub, function(submission) { + return new Date(submission.createdAt).getTime(); + }, ['desc']); - Fliplet.Modal.confirm({ - message: message - }).then(function (confirmed) { - if (!confirmed) { - return; - } + checkSubmissionStatus("appStore", asub); + checkSubmissionStatus("enterprise", esub); + checkSubmissionStatus("unsigned", usub); +} - saveUnsignedData(true); - }); - } else { - Fliplet.Modal.alert({ - message: 'Please configure your App Settings to contain the required information.' - }); - } +function getSubmissions() { + return Fliplet.App.Submissions.get(); +} + +function initialLoad(initial, timeout) { + if (!initial) { + initLoad = setTimeout(function() { + getSubmissions() + .then(function(submissions) { + iosSubmissionChecker(submissions); + initialLoad(false, 15000); + }); + }, timeout); } else { - $('.button-unsigned-request').html('Please wait '); - $('.button-unsigned-request').prop('disabled', true); - publishApp('unsigned'); - } + getSubmissions() + .then(function(submissions) { - // Gives time to Validator to apply classes - setTimeout(checkGroupErrors, 0); -}); + if (!submissions.length) { + return Promise.all([ + Fliplet.App.Submissions.create({ + platform: 'ios', + data: { + submissionType: "appStore" + } + }) + .then(function(submission) { + appStoreSubmission = submission; + }), + Fliplet.App.Submissions.create({ + platform: 'ios', + data: { + submissionType: "unsigned" + } + }) + .then(function(submission) { + unsignedSubmission = submission; + }), + Fliplet.App.Submissions.create({ + platform: 'ios', + data: { + submissionType: "enterprise" + } + }) + .then(function(submission) { + enterpriseSubmission = submission; + }) + ]); + } -/* SAVE PROGRESS CLICK */ -$('[data-app-store-save]').on('click', function() { - saveAppStoreData(); -}); -$('[data-enterprise-save]').on('click', function() { - saveEnterpriseData(); -}); -$('[data-unsigned-save]').on('click', function() { - saveUnsignedData(); -}); -$('[data-push-save]').on('click', function() { - savePushData(); -}); + return Fliplet.API.request({ + cache: true, + url: 'v1/user' + }) + .then(function(user) { + userInfo = user; + return submissionChecker(submissions); + }); + }) + .then(function() { + // Fliplet.Env.get('appId') + // Fliplet.Env.get('appName') + // Fliplet.Env.get('appSettings') -/* Credentials and Certificates App Store */ -$('.login-appStore-button').on('click', function() { - var $this = $(this); - $(this).html('Logging in...'); - $(this).addClass('disabled'); - var devEmail = $('#fl-store-appDevLogin').val(); - var devPass = $('#fl-store-appDevPass').val(); - var emailError = $('#fl-store-appDevLogin').data('error'); - var passError = $('#fl-store-appDevPass').data('error'); + return Promise.all([ + Fliplet.API.request({ + method: 'GET', + url: 'v1/apps/' + Fliplet.Env.get('appId') + }) + .then(function(result) { + appName = result.app.name; + appIcon = result.app.icon; + appSettings = result.app.settings; + }), + Fliplet.API.request({ + method: 'GET', + url: 'v1/organizations/' + Fliplet.Env.get('organizationId') + }) + .then(function(org) { + organizationName = org.name; + }) + ]); + }) + .then(function() { + if (appSettings.folderStructure) { + var structure = []; + hasFolders = true; + var appleOnly = _.filter(appSettings.folderStructure, function(obj) { + return obj.platform === 'apple'; + }); - // Remove errors - $('#fl-store-appDevLogin').parents('.form-group').removeClass('has-error has-danger'); - $('#fl-store-appDevLogin').next('.with-errors').html(''); - $('#fl-store-appDevPass').parents('.form-group').removeClass('has-error has-danger'); - $('#fl-store-appDevPass').next('.with-errors').html(''); - $this.nextAll('login-error').html(''); + return Promise.all(appleOnly.map(function(obj) { + return Fliplet.Media.Folders.get({folderId: obj.folderId}) + .then(function(result) { + var tempObject = { + type: obj.type, + folderContent: result + } - if (devEmail === '') { - $('#fl-store-appDevLogin').parents('.form-group').addClass('has-error has-danger'); - $('#fl-store-appDevLogin').next('.with-errors').html(emailError); - $(this).html('Log in'); - $(this).removeClass('disabled'); - Fliplet.Widget.autosize(); - } + structure.push(tempObject); + return Promise.resolve(structure); + }); + })) + .then(function() { + structure.forEach(function(el, idx) { + if (el.type === 'mobile') { + screenShotsMobile = el.folderContent.files + } + if (el.type === 'tablet') { + screenShotsTablet = el.folderContent.files + } + }); + }); + } else { + hasFolders = false; + return; + } + }) + .then(function() { + return Fliplet.API.request({ + method: 'GET', + url: 'v1/widget-instances/com.fliplet.push-notifications?appId=' + Fliplet.Env.get('appId') + }); + }) + .then(function(response) { + if (response.widgetInstance.settings && response.widgetInstance.settings) { + notificationSettings = response.widgetInstance.settings; + } else { + notificationSettings = {}; + } - if (devPass === '') { - $('#fl-store-appDevPass').parents('.form-group').addClass('has-error has-danger'); - $('#fl-store-appDevPass').next('.with-errors').html(passError); - $(this).html('Log in'); - $(this).removeClass('disabled'); - Fliplet.Widget.autosize(); + init(); + initialLoad(false, 5000); + }); } +} - if (devEmail !== '' && devPass !== '') { - setCredentials(organizationID, appStoreSubmission.id, { - type: 'apple', - status: 'created', - email: devEmail, - password: devPass - }) - .then(function() { - return appStoreTeamSetup(devEmail, $this); - }) - .catch(function(error) { - console.log(error); - if (error.responseJSON) { - $this.nextAll('.login-error').html(error.responseJSON.message); - } - $this.html('Log in'); - $this.removeClass('disabled'); - Fliplet.Widget.autosize(); - }); - } -}); +function prompt2FACode() { + // @TODO Update Fliplet.Modal in fliplet-api for simpler call + return Fliplet.Modal.prompt({ + title: 'Please enter the verification code to verify your login' + }).then(function (code) { + if (code === null) { + return null; + } -$('.log-out-appStore').on('click', function() { - setCredentials(organizationID, appStoreSubmission.id, { - email: null, - password: null, - teamId: null - }, false).then(function () { - appStoreLoggedIn = false; - $('#fl-store-appDevPass').prop('required', true); - $('.appStore-logged-email').html(''); - $('.appStore-login-details').removeClass('hidden'); - $('.appStore-logged-in, .appStore-more-options, .appStore-teams').removeClass('show'); + if (code === '') { + return Fliplet.Modal.alert({ + message: 'You must enter the verification code to log in' + }).then(function () { + return prompt2FACode(); + }); + } + + return code; }); -}); +} -$('[name="fl-store-distribution"]').on('change', function() { +/* ATTACH LISTENERS */ +$('[name="fl-store-screenshots"]').on('change', function() { var value = $(this).val(); + var id = $(this).attr('id'); + checkHasScreenshots(); - $('#fl-store-teams').prop('required',true); - - if (value === 'previous-file') { - if (appStoreCertificateReplaced) { - $('.appStore-previous-file-success').addClass('show'); - } + if (value === 'new' && !haveScreenshots) { + $('[data-item="fl-store-screenshots-new-warning"]').addClass('show'); - $('.appStore-generate-file, .appStore-generate-file-success, .appStore-upload-file').removeClass('show'); - $('#fl-store-certificate').prop('required',false); + $('[data-item="fl-store-screenshots-new"]').removeClass('show'); + $('[data-item="fl-store-screenshots-existing"]').removeClass('show'); } - if (value === 'generate-file') { - if (appStoreCertificateCreated) { - $('.appStore-generate-file-success').addClass('show'); - } else { - $('.appStore-generate-file').addClass('show'); - } + if (value === 'new' && haveScreenshots) { + $('[data-item="fl-store-screenshots-new-warning"]').removeClass('show'); + $('[data-item="fl-store-screenshots-new"]').addClass('show'); - $('.appStore-previous-file-success, .appStore-upload-file').removeClass('show'); - $('#fl-store-certificate').prop('required',false); + $('[data-item="fl-store-screenshots-existing"]').removeClass('show'); + + + _.take(screenShotsMobile, 4).forEach(function(thumb) { + $('.mobile-thumbs').append(addThumb(thumb)); + }); + + _.take(screenShotsTablet, 4).forEach(function(thumb) { + $('.tablet-thumbs').append(addThumb(thumb)); + }); } - if (value === 'upload-file') { - $('.appStore-upload-file').addClass('show'); - $('.appStore-previous-file-success, .appStore-generate-file, .appStore-generate-file-success').removeClass('show'); + if (value === 'existing') { + $('.app-details-appStore .app-screenshots').removeClass('has-error'); + $('[data-item="fl-store-screenshots-existing"]').addClass('show'); - $('#fl-store-certificate').prop('required',true); + $('[data-item="fl-store-screenshots-new-warning"]').removeClass('show'); + $('[data-item="fl-store-screenshots-new"]').removeClass('show'); } +}); + +$('[name="submissionType"]').on('change', function() { + var selectedOptionId = $(this).attr('id'); + + $('.fl-sb-panel').removeClass('show'); + $('.' + selectedOptionId).addClass('show'); + Fliplet.Widget.autosize(); }); -$('#fl-store-teams').on('change', function() { +$('[name="fl-store-credentials"]').on('change', function() { var value = $(this).val(); - var teamName = value ? $('#fl-store-teams').find(":selected").data('team-name') : ''; - if (value !== '') { - $('.appStore-more-options').addClass('show'); - $('.appStore-generate-cert').removeClass('disabled'); - $('.appStore-upload-certificate').removeClass('disabled'); + if (value === 'useOwn') { + $('.fl-store-credential.indented-area').removeClass('hidden'); } else { - $('.appStore-more-options').removeClass('show'); - $('.appStore-generate-cert').addClass('disabled'); - $('.appStore-upload-certificate').addClass('disabled'); + $('.fl-store-credential.indented-area').addClass('hidden'); } - var devEmail = $('#fl-store-appDevLogin').val(); - return refreshAppStoreOptions(devEmail, value, teamName); + Fliplet.Widget.autosize(); }); -$('.appStore-generate-cert').on('click', function() { - var $this = $(this); - $(this).html('Generating...'); - $(this).addClass('disabled'); - $('.generate-error').html(''); // Cleans errors - var teamId = $('#fl-store-teams').val(); - appStoreTeamId = teamId; - var teamName = $('#fl-store-teams').find(":selected").data('team-name'); +$('.fl-sb-appStore [change-bundleid], .fl-sb-enterprise [change-bundleid], .fl-sb-unsigned [change-bundleid]').on('click', function() { + Fliplet.Modal.confirm({ + message: 'Are you sure you want to change the unique Bundle ID?' + }).then(function (confirmed) { + if (!confirmed) { + return; + } - return setCredentials(organizationID, appStoreSubmission.id, { - teamId: teamId, - teamName: teamName - }) - .then(function() { - return createCertificates({ - organizationId: organizationID, - submissionId: appStoreSubmission.id - }) - .then(function(response) { - var p12Url = Fliplet.Env.get('apiUrl') + 'v1/organizations/' + organizationID + '/credentials/submission-' + appStoreSubmission.id + '/download/p12' - appStoreCertificateCreated = true; - $('.appStore-generate-file-success').find('.appStore-file-name-success').html(response.certificate.name); - $('.appStore-generate-file-success').find('.appStore-file-expire-success').html(moment(response.certificate.expiresAt).format('MMMM Do YYYY')); - $('.appStore-generate-file-success').find('.appStore-file-download-success').attr('href', p12Url); - $('.appStore-generate-file').removeClass('show'); - $('.appStore-generate-file-success').addClass('show'); - $this.html('Generate certificate'); - $this.removeClass('disabled'); - }); - }) - .catch(function(error) { - $this.html('Generate certificate'); - $this.removeClass('disabled'); - if (error.responseJSON.message) { - $('.generate-error').html(error.responseJSON.message); - } - }); + $('.fl-bundleId-holder').addClass('hidden'); + $('.fl-bundleId-field').addClass('show'); + + Fliplet.Widget.autosize(); + }); }); -$('#fl-store-certificate').on('change', function() { - appStoreFileField = this; - var fileName = appStoreFileField.value.replace(/\\/g, '/').replace(/.*\//, ''); +$('.panel-group') + .on('shown.bs.collapse', '.panel-collapse', function() { + Fliplet.Widget.autosize(); + }) + .on('hidden.bs.collapse', '.panel-collapse', function() { + Fliplet.Widget.autosize(); + }); - if (appStoreFileField.files && appStoreFileField.files[0]) { - $('#fl-store-certificate-label').val(fileName); +$('a[data-toggle="tab"]') + .on('shown.bs.tab', function() { + Fliplet.Widget.autosize(); + }) + .on('hidden.bs.tab', function() { + Fliplet.Widget.autosize(); + }); + +$('[name="fl-store-keywords"]').on('tokenfield:createtoken', function(e) { + var currentValue = e.currentTarget.value.replace(/,\s+/g, ','); + var newValue = e.attrs.value; + var oldAndNew = currentValue + ',' + newValue; + + if (oldAndNew.length > 100) { + e.preventDefault(); } }); -$('.appStore-replace-cert').on('click', function() { - var $this = $(this); - $(this).html('Replacing...'); - $(this).addClass('disabled'); - $('.replace-error').html(''); // Cleans errors - var teamId = appStorePreviousCredential ? appStorePreviousCredential.teamId : ''; - appStoreTeamId = teamId; - var teamName = appStorePreviousCredential ? appStorePreviousCredential.teamName : ''; +$('.redirectToSettings, [data-change-settings]').on('click', function(event) { + event.preventDefault(); - if (appStorePreviousCredential.certificate && appStorePreviousCredential.certificate.id) { - return revokeCertificate(organizationID, appStoreSubmission.id, appStorePreviousCredential.certificate.id) - .then(function() { - return setCredentials(organizationID, appStoreSubmission.id, { - teamId: teamId, - teamName: teamName - }) - .then(function() { - return createCertificates({ - organizationId: organizationID, - submissionId: appStoreSubmission.id - }) - .then(function(response) { - var p12Url = Fliplet.Env.get('apiUrl') + 'v1/organizations/' + organizationID + '/credentials/submission-' + appStoreSubmission.id + '/download/p12' - appStoreCertificateReplaced = true; - $('.appStore-previous-file-success').find('.appStore-file-name-success').html(response.certificate.name); - $('.appStore-previous-file-success').find('.appStore-file-expire-success').html(moment(response.certificate.expiresAt).format('MMMM Do YYYY')); - $('.appStore-previous-file-success').find('.appStore-file-download-success').attr('href', p12Url); - $('.appStore-previous-file-success').addClass('show'); - $this.html('Replace certificate'); - $this.removeClass('disabled'); - }); - }); - }) - .catch(function(error) { - $this.html('Replace certificate'); - $this.removeClass('disabled'); - if (error.responseJSON.message) { - $('.replace-error').html(error.responseJSON.message); - } - }); - } else { - $this.html('Replace certificate'); - $this.removeClass('disabled'); - $('.replace-error').html("We could not replace the certificate.\nPlease log into your https://developer.apple.com/account/ and revoke the certificate and create a new one using Fliplet."); + Fliplet.Studio.emit('close-overlay', { + name: 'publish-apple' + }); + + Fliplet.Studio.emit('overlay', { + name: 'app-settings', + options: { + size: 'large', + title: 'App Settings', + section: 'appSettingsGeneral', + appId: Fliplet.Env.get('appId') + } + }); +}); + +$('[data-change-assets]').on('click', function(event) { + event.preventDefault(); + + Fliplet.Studio.emit('close-overlay', { + name: 'publish-apple' + }); + + Fliplet.Studio.emit('overlay', { + name: 'app-settings', + options: { + size: 'large', + title: 'App Settings', + section: 'launchAssets', + appId: Fliplet.Env.get('appId') } + }); +}); +$('#appStoreConfiguration, #enterpriseConfiguration, #unsignedConfiguration').on('validated.bs.validator', function() { + checkGroupErrors(); + Fliplet.Widget.autosize(); }); -/**/ -/* Credentials and Certificates Enterprise */ -$('.login-enterprise-button').on('click', function() { - var $this = $(this); - $(this).html('Logging in...'); - $(this).addClass('disabled'); - var devEmail = $('#fl-ent-appDevLogin').val(); - var devPass = $('#fl-ent-appDevPass').val(); - var emailError = $('#fl-ent-distributionnt-appDevLogin').data('error'); - var passError = $('#fl-ent-appDevPass').data('error'); +$('#appStoreConfiguration').validator().on('submit', function(event) { + if (event.isDefaultPrevented()) { + // Gives time to Validator to apply classes + setTimeout(checkGroupErrors, 0); + Fliplet.Modal.alert({ + message: 'Please fill in all the required information.' + }); + return; + } - // Remove errors - $('#fl-ent-appDevLogin').parents('.form-group').removeClass('has-error has-danger'); - $('#fl-ent-appDevLogin').next('.with-errors').html(''); - $('#fl-ent-appDevPass').parents('.form-group').removeClass('has-error has-danger'); - $('#fl-ent-appDevPass').next('.with-errors').html(''); - $this.nextAll('login-error').html(''); + event.preventDefault(); - if (devEmail === '') { - $('#fl-ent-appDevLogin').parents('.form-group').addClass('has-error has-danger'); - $('#fl-ent-appDevLogin').next('.with-errors').html(emailError); - $(this).html('Log in'); - $(this).removeClass('disabled'); - Fliplet.Widget.autosize(); + if ($('[name="fl-store-screenshots"]:checked').val() === 'new' && !haveScreenshots) { + Fliplet.Modal.alert({ + message: 'You need to add screenshots before submitting' + }); + return; } - if (devPass === '') { - $('#fl-ent-appDevPass').parents('.form-group').addClass('has-error has-danger'); - $('#fl-ent-appDevPass').next('.with-errors').html(passError); - $(this).html('Log in'); - $(this).removeClass('disabled'); - Fliplet.Widget.autosize(); + if (!validateScreenshots()) { + return; } - if (devEmail !== '' && devPass !== '') { - setCredentials(organizationID, enterpriseSubmission.id, { - type: 'apple-enterprise', - status: 'created', - email: devEmail, - password: devPass - }) - .then(function() { - $('[name="fl-ent-distribution"][value="generate-file"]').prop('checked', true).trigger('change'); - return enterpriseTeamSetup(devEmail, $this); - }) - .catch(function(error) { - if (error.responseJSON) { - $this.nextAll('.login-error').html(error.responseJSON.message); - } - $this.html('Log in'); - $this.removeClass('disabled'); - Fliplet.Widget.autosize(); - }); - } -}); + if (appInfo && appInfo.productionAppId) { + if (allAppData.indexOf('appStore') > -1) { + if (appStoreLoggedIn) { + var certificateKind = $('[name="fl-store-distribution"]:checked').val(); -$('.log-out-enterprise').on('click', function() { - setCredentials(organizationID, enterpriseSubmission.id, { - email: null, - password: null, - teamId: null - }, false).then(function () { - enterpriseLoggedIn = false; - $('#fl-ent-appDevPass').prop('required', true); - $('.enterprise-logged-email').html(''); - $('.enterprise-login-details').removeClass('hidden'); - $('.enterprise-logged-in, .enterprise-more-options, .enterprise-teams').removeClass('show'); - }); -}); + if (certificateKind === 'generate-file' && !appStoreCertificateCreated) { + Fliplet.Modal.alert({ + message: 'You need to generate a certificate before requesting a submission' + }); + return; + } -$('[name="fl-ent-distribution"]').on('change', function() { - var value = $(this).val(); + if (certificateKind === 'upload-file' && (!appStoreFileField.files || !appStoreFileField.files[0])){ + Fliplet.Modal.alert({ + message: 'You need to upload a certificate before requesting a submission' + }); + return; + } - $('#fl-ent-teams').prop('required',true); + var message = 'Are you sure you wish to update your published app?'; - if (value === 'previous-file') { - if (enterpriseCertificateReplaced) { - $('.enterprise-previous-file-success').addClass('show'); - } + if (appStoreSubmission.status === "started") { + message = 'Are you sure you wish to request your app to be published?'; + } - $('.enterprise-generate-file, .enterprise-generate-file-success, .enterprise-upload-file').removeClass('show'); - } - if (value === 'generate-file') { - if (enterpriseCertificateCreated) { - $('.enterprise-generate-file-success').addClass('show'); + Fliplet.Modal.confirm({ + message: message + }).then(function (confirmed) { + if (!confirmed) { + return; + } + + saveAppStoreData(true); + }); + } else { + Fliplet.Modal.alert({ + message: 'You need to login with your Apple developer account details.
    Select one option to provide use with a distribution certificate.' + }); + } } else { - $('.enterprise-generate-file').addClass('show'); + Fliplet.Modal.alert({ + message: 'Please configure your App Settings to contain the required information.' + }); } - $('.enterprise-previous-file-success, .enterprise-upload-file').removeClass('show'); - $('#fl-ent-certificate').prop('required',false); - } - if (value === 'upload-file') { - $('.enterprise-upload-file').addClass('show'); - $('.enterprise-previous-file-success, .enterprise-generate-file, .enterprise-generate-file-success').removeClass('show'); - $('#fl-ent-certificate').prop('required',true); + } else { + $('.button-appStore-request').html('Please wait '); + $('.button-appStore-request').prop('disabled', true); + publishApp('appStore'); } - Fliplet.Widget.autosize(); + + // Gives time to Validator to apply classes + setTimeout(checkGroupErrors, 0); }); -$('#fl-ent-teams').on('change', function() { - var value = $(this).val(); - var teamName = value ? $('#fl-ent-teams').find(":selected").data('team-name') : ''; +$('#enterpriseConfiguration').validator().on('submit', function(event) { + if (event.isDefaultPrevented()) { + // Gives time to Validator to apply classes + setTimeout(checkGroupErrors, 0); + Fliplet.Modal.alert({ + message: 'Please fill in all the required information.' + }); + return; + } - if (value !== '') { - $('.enterprise-more-options').addClass('show'); - $('.enterprise-generate-cert').removeClass('disabled'); - $('.enterprise-upload-certificate').removeClass('disabled'); - } else { - $('.enterprise-more-options').removeClass('show'); - $('.enterprise-generate-cert').addClass('disabled'); - $('.enterprise-upload-certificate').addClass('disabled'); + event.preventDefault(); + + if (!enterpriseManual && !enterpriseLoggedIn) { + Fliplet.Modal.alert({ + message: 'Please log in with the Apple Developer Account or choose to enter the data manually.' + }); + return; } - var devEmail = $('#fl-ent-appDevLogin').val(); - return refreshAppEnterpriseOptions(devEmail, value, teamName); -}); + var credentialKind = $('[name="fl-ent-distribution"]:checked').val(); -$('.enterprise-generate-cert').on('click', function() { - var $this = $(this); - $(this).html('Generating...'); - $(this).addClass('disabled'); - $('.generate-error').html(''); // Cleans errors - var teamId = $('#fl-ent-teams').val(); - enterpriseTeamId = teamId; - var teamName = $('#fl-ent-teams').find(":selected").data('team-name'); + if (!enterpriseManual) { + if (credentialKind === 'generate-file' && !enterpriseCertificateCreated) { + Fliplet.Modal.alert({ + message: 'You need to generate a certificate before requesting a submission' + }); + return; + } - return setCredentials(organizationID, enterpriseSubmission.id, { - teamId: teamId, - teamName: teamName - }) - .then(function() { - return createCertificates({ - organizationId: organizationID, - submissionId: enterpriseSubmission.id, - inHouse: true - }) - .then(function(response) { - var p12Url = Fliplet.Env.get('apiUrl') + 'v1/organizations/' + organizationID + '/credentials/submission-' + enterpriseSubmission.id + '/download/p12' - enterpriseCertificateCreated = true; - $('.enterprise-generate-file-success').find('.enterprise-file-name-success').html(response.certificate.name); - $('.enterprise-generate-file-success').find('.enterprise-file-expire-success').html(moment(response.certificate.expiresAt).format('MMMM Do YYYY')); - $('.enterprise-generate-file-success').find('.enterprise-file-download-success').attr('href', p12Url); - $('.enterprise-generate-file').removeClass('show'); - $('.enterprise-generate-file-success').addClass('show'); - $this.html('Generate certificate'); - $this.removeClass('disabled'); - }); - }) - .catch(function(error) { - $this.html('Generate certificate'); - $this.removeClass('disabled'); - if (error.responseJSON.message) { - $('.generate-error').html(error.responseJSON.message); + if (credentialKind === 'upload-file' && (!enterpriseFileField.files || !enterpriseFileField.files[0])) { + Fliplet.Modal.alert({ + message: 'You need to upload a certificate before requesting a submission' + }); + return; + } + } + + if (appInfo && appInfo.productionAppId) { + if (allAppData.indexOf('enterprise') > -1) { + var message = 'Are you sure you wish to update your published app?'; + + if (enterpriseSubmission.status === "started") { + message = 'Are you sure you wish to request your app to be published?'; } - }); -}); -$('#fl-ent-certificate').on('change', function() { - enterpriseFileField = this; - var fileName = enterpriseFileField.value.replace(/\\/g, '/').replace(/.*\//, ''); + Fliplet.Modal.confirm({ + message: message + }).then(function (confirmed) { + if (!confirmed) { + return; + } - if (enterpriseFileField.files && enterpriseFileField.files[0]) { - $('#fl-ent-certificate-label').val(fileName); + saveEnterpriseData(true); + }); + } else { + Fliplet.Modal.alert({ + message: 'Please configure your App Settings to contain the required information.' + }); + } + } else { + $('.button-enterprise-request').html('Please wait '); + $('.button-enterprise-request').prop('disabled', true); + publishApp('enterprise'); } -}); -$('#fl-ent-certificate-manual-details').on('change', function() { - enterpriseFileFieldManual = this; - var fileName = enterpriseFileFieldManual.value.replace(/\\/g, '/').replace(/.*\//, ''); + // Gives time to Validator to apply classes + setTimeout(checkGroupErrors, 0); +}); - if (enterpriseFileFieldManual.files && enterpriseFileFieldManual.files[0]) { - $('#fl-ent-certificate-manual-details-label').val(fileName); +$('#unsignedConfiguration').validator().on('submit', function(event) { + if (event.isDefaultPrevented()) { + // Gives time to Validator to apply classes + setTimeout(checkGroupErrors, 0); + Fliplet.Modal.alert({ + message: 'Please fill in all the required information.' + }); + return; } -}); -$('#fl-ent-mobileprovision-manual-details').on('change', function() { - enterpriseFileProvisionFieldManual = this; - var fileName = enterpriseFileProvisionFieldManual.value.replace(/\\/g, '/').replace(/.*\//, ''); + event.preventDefault(); - if (enterpriseFileProvisionFieldManual.files && enterpriseFileProvisionFieldManual.files[0]) { - $('#fl-ent-mobileprovision-manual-details-label').val(fileName); - } -}); + if (appInfo && appInfo.productionAppId) { + if (allAppData.indexOf('unsigned') > -1) { + var message = 'Are you sure you wish to update your published app?'; -$('.enterprise-replace-cert').on('click', function() { - var $this = $(this); - $(this).html('Replacing...'); - $(this).addClass('disabled'); - $('.replace-error').html(''); // Cleans errors - var teamId = enterprisePreviousCredential ? enterprisePreviousCredential.teamId : ''; - enterpriseTeamId = teamId; - var teamName = enterprisePreviousCredential ? enterprisePreviousCredential.teamName : ''; + if (unsignedSubmission.status === "started") { + message = 'Are you sure you wish to request your app to be published?'; + } - if (enterprisePreviousCredential.certificate && enterprisePreviousCredential.certificate.id) { - return revokeCertificate(organizationID, enterpriseSubmission.id, enterprisePreviousCredential.certificate.id) - .then(function() { - return setCredentials(organizationID, enterpriseSubmission.id, { - teamId: teamId, - teamName: teamName - }) - .then(function() { - return createCertificates({ - organiazationId: organizationID, - submissionId: enterpriseSubmission.id, - inHouse: true - }) - .then(function(response) { - var p12Url = Fliplet.Env.get('apiUrl') + 'v1/organizations/' + organizationID + '/credentials/submission-' + enterpriseSubmission.id + '/download/p12' - enterpriseCertificateReplaced = true; - $('.enterprise-previous-file-success').find('.enterprise-file-name-success').html(response.certificate.name); - $('.enterprise-previous-file-success').find('.enterprise-file-expire-success').html(moment(response.certificate.expiresAt).format('MMMM Do YYYY')); - $('.enterprise-previous-file-success').find('.enterprise-file-download-success').attr('href', p12Url); - $('.enterprise-previous-file-success').addClass('show'); - $this.html('Replace certificate'); - $this.removeClass('disabled'); - }); - }); - }) - .catch(function(error) { - $this.html('Replace certificate'); - $this.removeClass('disabled'); - if (error.responseJSON.message) { - $('.replace-error').html(error.responseJSON.message); + Fliplet.Modal.confirm({ + message: message + }).then(function (confirmed) { + if (!confirmed) { + return; } + + saveUnsignedData(true); + }); + } else { + Fliplet.Modal.alert({ + message: 'Please configure your App Settings to contain the required information.' }); + } } else { - $this.html('Replace certificate'); - $this.removeClass('disabled'); - $('.replace-error').html("We could not replace the certificate.\nPlease log into your https://developer.apple.com/account/ and revoke the certificate and create a new one using Fliplet."); + $('.button-unsigned-request').html('Please wait '); + $('.button-unsigned-request').prop('disabled', true); + publishApp('unsigned'); } -}); - -$('.ent-enter-manually').on('click', function() { - $('.enterprise-login-details').addClass('hidden'); - $('.enterprise-manual-details').addClass('show'); - enterpriseManual = true; - - $('#fl-ent-appDevLogin').prop('required', false); - $('#fl-ent-appDevPass').prop('required', false); - $('#fl-ent-teams').prop('required',false); - $('#fl-ent-teamName').prop('required', true); - $('#fl-ent-teamId').prop('required', true); - $('#fl-ent-certificate-manual-details').prop('required', true); - $('#fl-ent-mobileprovision-manual-details').prop('required', true); + // Gives time to Validator to apply classes + setTimeout(checkGroupErrors, 0); }); -$('.enterprise-back-login').on('click', function() { - $('.enterprise-login-details').removeClass('hidden'); - $('.enterprise-manual-details').removeClass('show'); - enterpriseManual = false; - - $('#fl-ent-appDevLogin').prop('required', true); - $('#fl-ent-appDevPass').prop('required', true); - $('#fl-ent-teams').prop('required',true); - - $('#fl-ent-teamName').prop('required', false); - $('#fl-ent-teamId').prop('required', false); - $('#fl-ent-certificate-manual-details').prop('required', false); - $('#fl-ent-mobileprovision-manual-details').prop('required', false); +/* SAVE PROGRESS CLICK */ +$('[data-app-store-save]').on('click', function() { + saveAppStoreData(); +}); +$('[data-enterprise-save]').on('click', function() { + saveEnterpriseData(); +}); +$('[data-unsigned-save]').on('click', function() { + saveUnsignedData(); +}); +$('[data-push-save]').on('click', function() { + savePushData(); }); -/**/ -$(document).on('click', '[data-cancel-build-id]', function() { - var buildId = $(this).data('cancel-build-id'); +/* Credentials and Certificates App Store */ +$('.login-appStore-button').on('click', function() { + var $this = $(this); + $(this).html('Logging in...'); + $(this).addClass('disabled'); + var devEmail = $('#fl-store-appDevLogin').val(); + var devPass = $('#fl-store-appDevPass').val(); + var emailError = $('#fl-store-appDevLogin').data('error'); + var passError = $('#fl-store-appDevPass').data('error'); - Fliplet.API.request({ - method: 'DELETE', - url: 'v1/apps/' + Fliplet.Env.get('appId') + '/submissions/' + buildId - }) - .then(function() { - clearTimeout(initLoad); - initialLoad(false, 0); - }) -}); + // Remove errors + $('#fl-store-appDevLogin').parents('.form-group').removeClass('has-error has-danger'); + $('#fl-store-appDevLogin').next('.with-errors').html(''); + $('#fl-store-appDevPass').parents('.form-group').removeClass('has-error has-danger'); + $('#fl-store-appDevPass').next('.with-errors').html(''); + $this.nextAll('login-error').html(''); -$('.browse-files').on('click', function(e) { - e.preventDefault(); + if (devEmail === '') { + $('#fl-store-appDevLogin').parents('.form-group').addClass('has-error has-danger'); + $('#fl-store-appDevLogin').next('.with-errors').html(emailError); + $(this).html('Log in'); + $(this).removeClass('disabled'); + Fliplet.Widget.autosize(); + } - Fliplet.Studio.emit('overlay', { - name: 'widget', - options: { - size: 'large', - package: 'com.fliplet.file-manager', - title: 'File Manager', - classes: 'data-source-overlay', - data: { - context: 'overlay', - appId: Fliplet.Env.get('appId') + if (devPass === '') { + $('#fl-store-appDevPass').parents('.form-group').addClass('has-error has-danger'); + $('#fl-store-appDevPass').next('.with-errors').html(passError); + $(this).html('Log in'); + $(this).removeClass('disabled'); + Fliplet.Widget.autosize(); + } + + if (devEmail !== '' && devPass !== '') { + setCredentials(organizationID, appStoreSubmission.id, { + type: 'apple', + status: 'created', + email: devEmail, + password: devPass + }) + .then(function() { + return appStoreTeamSetup(devEmail, $this); + }) + .catch(function(error) { + console.log(error); + if (error.responseJSON) { + $this.nextAll('.login-error').html(error.responseJSON.message); } - } - }); + $this.html('Log in'); + $this.removeClass('disabled'); + Fliplet.Widget.autosize(); + }); + } }); -/* INIT */ -$('#appStoreConfiguration, #enterpriseConfiguration, #unsignedConfiguration').validator().off('change.bs.validator focusout.bs.validator'); -$('[name="submissionType"][value="appStore"]').prop('checked', true).trigger('change'); - -function publishApp(context) { - var options = { - release: { - type: 'silent', - changelog: 'Initial version' - } - }; - Fliplet.API.request({ - method: 'POST', - url: 'v1/apps/' + Fliplet.Env.get('appId') + '/publish', - data: options - }).then(function(response) { - // Update appInfo - appInfo.productionAppId = response.app.id; - - switch(context) { - case 'appStore': - $('.button-appStore-request').html('Request App '); - $('.button-appStore-request').prop('disabled', false); - $('#appStoreConfiguration').validator().trigger('submit'); - break; - case 'enterprise': - $('.button-enterprise-request').html('Request App '); - $('.button-enterprise-request').prop('disabled', false); - $('#enterpriseConfiguration').validator().trigger('submit'); - break; - case 'unsigned': - $('.button-unsigned-request').html('Request App '); - $('.button-unsigned-request').prop('disabled', false); - $('#unsignedConfiguration').validator().trigger('submit'); - break; - default: - break; - } +$('.log-out-appStore').on('click', function() { + setCredentials(organizationID, appStoreSubmission.id, { + email: null, + password: null, + teamId: null + }, false).then(function () { + appStoreLoggedIn = false; + $('#fl-store-appDevPass').prop('required', true); + $('.appStore-logged-email').html(''); + $('.appStore-login-details').removeClass('hidden'); + $('.appStore-logged-in, .appStore-more-options, .appStore-teams').removeClass('show'); }); -} +}); -function compileStatusTable(withData, origin, buildsData) { - if (withData) { - var template = Handlebars.compile(statusTableTemplate); - var html = template(buildsData); +$('[name="fl-store-distribution"]').on('change', function() { + var value = $(this).val(); - if (origin === "appStore") { - $statusAppStoreTableElement.html(html); - } - if (origin === "enterprise") { - $statusEnterpriseTableElement.html(html); - } - if (origin === "unsigned") { - $statusUnsignedTableElement.html(html); - } - } else { - if (origin === "appStore") { - $statusAppStoreTableElement.html(''); - } - if (origin === "enterprise") { - $statusEnterpriseTableElement.html(''); + $('#fl-store-teams').prop('required',true); + + if (value === 'previous-file') { + if (appStoreCertificateReplaced) { + $('.appStore-previous-file-success').addClass('show'); } - if (origin === "unsigned") { - $statusUnsignedTableElement.html(''); + + $('.appStore-generate-file, .appStore-generate-file-success, .appStore-upload-file').removeClass('show'); + $('#fl-store-certificate').prop('required',false); + } + if (value === 'generate-file') { + if (appStoreCertificateCreated) { + $('.appStore-generate-file-success').addClass('show'); + } else { + $('.appStore-generate-file').addClass('show'); } + + $('.appStore-previous-file-success, .appStore-upload-file').removeClass('show'); + $('#fl-store-certificate').prop('required',false); } + if (value === 'upload-file') { + $('.appStore-upload-file').addClass('show'); + $('.appStore-previous-file-success, .appStore-generate-file, .appStore-generate-file-success').removeClass('show'); + $('#fl-store-certificate').prop('required',true); + } Fliplet.Widget.autosize(); -} +}); -function checkSubmissionStatus(origin, iosSubmissions) { - var submissionsToShow = _.filter(iosSubmissions, function(submission) { - return submission.status === "queued" || submission.status === "submitted" || submission.status === "processing" || submission.status === "completed" || submission.status === "failed" || submission.status === "cancelled" || submission.status === "ready-for-testing" || submission.status === "tested"; - }); +$('#fl-store-teams').on('change', function() { + var value = $(this).val(); + var teamName = value ? $('#fl-store-teams').find(":selected").data('team-name') : ''; - var buildsData = []; - if (submissionsToShow.length) { - submissionsToShow.forEach(function(submission) { - var build = {}; - var appBuild; - var debugHtmlPage; + if (value !== '') { + $('.appStore-more-options').addClass('show'); + $('.appStore-generate-cert').removeClass('disabled'); + $('.appStore-upload-certificate').removeClass('disabled'); + } else { + $('.appStore-more-options').removeClass('show'); + $('.appStore-generate-cert').addClass('disabled'); + $('.appStore-upload-certificate').addClass('disabled'); + } - // Default copy for testing status for different users - if (submission.status === 'ready-for-testing') { - if (userInfo.user && (userInfo.user.isAdmin || userInfo.user.isImpersonating)) { - // Fliplet users - build.testingStatus = 'Ready for testing'; - build.testingMessage = 'App is ready for testing'; - } else { - // Normal users - build.testingStatus = 'In testing'; - build.testingMessage = 'Your app is being tested by Fliplet'; - } - } + var devEmail = $('#fl-store-appDevLogin').val(); + return refreshAppStoreOptions(devEmail, value, teamName); +}); - if (submission.result.appBuild && submission.result.appBuild.files) { - appBuild = _.find(submission.result.appBuild.files, function(file) { - return file.contentType === 'application/octet-stream'; - }); - } else if (submission.data.previousResults && submission.data.previousResults.appBuild && submission.data.previousResults.appBuild.files) { - appBuild = _.find(submission.data.previousResults.appBuild.files, function(file) { - return file.contentType === 'application/octet-stream'; - }); - } +$('.appStore-generate-cert').on('click', function() { + var $this = $(this); + $(this).html('Generating...'); + $(this).addClass('disabled'); + $('.generate-error').html(''); // Cleans errors + var teamId = $('#fl-store-teams').val(); + appStoreTeamId = teamId; + var teamName = $('#fl-store-teams').find(":selected").data('team-name'); - if (submission.result.debugHtmlPage && submission.result.debugHtmlPage.files) { - debugHtmlPage = _.find(submission.result.debugHtmlPage.files, function(file) { - return file.contentType === 'text/html'; - }); - } else if (submission.data.previousResults && submission.data.previousResults.debugHtmlPage && submission.data.previousResults.debugHtmlPage.files) { - debugHtmlPage = _.find(submission.data.previousResults.debugHtmlPage.files, function(file) { - return file.contentType === 'text/html'; + return setCredentials(organizationID, appStoreSubmission.id, { + teamId: teamId, + teamName: teamName + }) + .then(function() { + return createCertificates({ + organizationId: organizationID, + submissionId: appStoreSubmission.id + }) + .then(function(response) { + var p12Url = Fliplet.Env.get('apiUrl') + 'v1/organizations/' + organizationID + '/credentials/submission-' + appStoreSubmission.id + '/download/p12' + appStoreCertificateCreated = true; + $('.appStore-generate-file-success').find('.appStore-file-name-success').html(response.certificate.name); + $('.appStore-generate-file-success').find('.appStore-file-expire-success').html(moment(response.certificate.expiresAt).format('MMMM Do YYYY')); + $('.appStore-generate-file-success').find('.appStore-file-download-success').attr('href', p12Url); + $('.appStore-generate-file').removeClass('show'); + $('.appStore-generate-file-success').addClass('show'); + $this.html('Generate certificate'); + $this.removeClass('disabled'); }); + }) + .catch(function(error) { + $this.html('Generate certificate'); + $this.removeClass('disabled'); + if (error.responseJSON.message) { + $('.generate-error').html(error.responseJSON.message); } - - build.id = submission.id; - build.updatedAt = ((submission.status === 'completed' || submission.status === 'failed' || submission.status === 'cancelled' || submission.status === 'ready-for-testing' || submission.status === 'tested') && submission.updatedAt) ? - moment(submission.updatedAt).format('MMM Do YYYY, h:mm:ss a') : - ''; - build.submittedAt = ((submission.status === 'queued' || submission.status === 'submitted') && submission.submittedAt) ? - moment(submission.submittedAt).format('MMM Do YYYY, h:mm:ss a') : - ''; - build[submission.status] = true; - build.fileUrl = appBuild ? appBuild.url : ''; - - if (submission.result.message) { - build.message = submission.result.message; - } - - if (userInfo.user && (userInfo.user.isAdmin || userInfo.user.isImpersonating)) { - build.debugFileUrl = debugHtmlPage ? debugHtmlPage.url : ''; - } - - buildsData.push(build); }); +}); - compileStatusTable(true, origin, buildsData); - } else { - compileStatusTable(false, origin); - } -} - -function submissionChecker(submissions) { - var asub = _.filter(submissions, function(submission) { - return submission.data.submissionType === "appStore" && submission.platform === "ios"; - }); +$('#fl-store-certificate').on('change', function() { + appStoreFileField = this; + var fileName = appStoreFileField.value.replace(/\\/g, '/').replace(/.*\//, ''); - var completedAsub = _.filter(asub, function(submission) { - return submission.status === "completed"; - }); + if (appStoreFileField.files && appStoreFileField.files[0]) { + $('#fl-store-certificate-label').val(fileName); + } +}); - //Get the Submission data from the first completed submission, it has the certification values that are in use on the app store. - previousAppStoreSubmission = _.minBy(completedAsub, function(el) { - return el.id; - }); +$('.appStore-replace-cert').on('click', function() { + var $this = $(this); + $(this).html('Replacing...'); + $(this).addClass('disabled'); + $('.replace-error').html(''); // Cleans errors + var teamId = appStorePreviousCredential ? appStorePreviousCredential.teamId : ''; + appStoreTeamId = teamId; + var teamName = appStorePreviousCredential ? appStorePreviousCredential.teamName : ''; - appStoreSubmissionInStore = (completedAsub.length > 0); + if (appStorePreviousCredential.certificate && appStorePreviousCredential.certificate.id) { + return revokeCertificate(organizationID, appStoreSubmission.id, appStorePreviousCredential.certificate.id) + .then(function() { + return setCredentials(organizationID, appStoreSubmission.id, { + teamId: teamId, + teamName: teamName + }) + .then(function() { + return createCertificates({ + organizationId: organizationID, + submissionId: appStoreSubmission.id + }) + .then(function(response) { + var p12Url = Fliplet.Env.get('apiUrl') + 'v1/organizations/' + organizationID + '/credentials/submission-' + appStoreSubmission.id + '/download/p12' + appStoreCertificateReplaced = true; + $('.appStore-previous-file-success').find('.appStore-file-name-success').html(response.certificate.name); + $('.appStore-previous-file-success').find('.appStore-file-expire-success').html(moment(response.certificate.expiresAt).format('MMMM Do YYYY')); + $('.appStore-previous-file-success').find('.appStore-file-download-success').attr('href', p12Url); + $('.appStore-previous-file-success').addClass('show'); + $this.html('Replace certificate'); + $this.removeClass('disabled'); + }); + }); + }) + .catch(function(error) { + $this.html('Replace certificate'); + $this.removeClass('disabled'); + if (error.responseJSON.message) { + $('.replace-error').html(error.responseJSON.message); + } + }); + } else { + $this.html('Replace certificate'); + $this.removeClass('disabled'); + $('.replace-error').html("We could not replace the certificate.\nPlease log into your https://developer.apple.com/account/ and revoke the certificate and create a new one using Fliplet."); + } +}); +/**/ - asub = _.orderBy(asub, function(submission) { - return new Date(submission.createdAt).getTime(); - }, ['desc']); - checkSubmissionStatus("appStore", asub); +/* Credentials and Certificates Enterprise */ +$('.login-enterprise-button').on('click', function() { + var $this = $(this); + $(this).html('Logging in...'); + $(this).addClass('disabled'); + var devEmail = $('#fl-ent-appDevLogin').val(); + var devPass = $('#fl-ent-appDevPass').val(); + var emailError = $('#fl-ent-distributionnt-appDevLogin').data('error'); + var passError = $('#fl-ent-appDevPass').data('error'); - appStoreSubmission = _.maxBy(asub, function(el) { - return new Date(el.createdAt).getTime(); - }); + // Remove errors + $('#fl-ent-appDevLogin').parents('.form-group').removeClass('has-error has-danger'); + $('#fl-ent-appDevLogin').next('.with-errors').html(''); + $('#fl-ent-appDevPass').parents('.form-group').removeClass('has-error has-danger'); + $('#fl-ent-appDevPass').next('.with-errors').html(''); + $this.nextAll('login-error').html(''); - if (!appStoreSubmission) { - appStoreSubmission = {}; + if (devEmail === '') { + $('#fl-ent-appDevLogin').parents('.form-group').addClass('has-error has-danger'); + $('#fl-ent-appDevLogin').next('.with-errors').html(emailError); + $(this).html('Log in'); + $(this).removeClass('disabled'); + Fliplet.Widget.autosize(); } - var cloneAppStoreCredentialsPromise = Promise.resolve(); - if (appStoreSubmission.data && !appStoreSubmission.data['fl-credentials']) { - - var prevSubCred = _.filter(asub, function(submission) { - return submission.data && submission.data['fl-credentials']; - }); + if (devPass === '') { + $('#fl-ent-appDevPass').parents('.form-group').addClass('has-error has-danger'); + $('#fl-ent-appDevPass').next('.with-errors').html(passError); + $(this).html('Log in'); + $(this).removeClass('disabled'); + Fliplet.Widget.autosize(); + } - var previousSubWithCredentials = _.maxBy(prevSubCred, function(el) { - return new Date(el.createdAt).getTime(); + if (devEmail !== '' && devPass !== '') { + setCredentials(organizationID, enterpriseSubmission.id, { + type: 'apple-enterprise', + status: 'created', + email: devEmail, + password: devPass + }) + .then(function() { + $('[name="fl-ent-distribution"][value="generate-file"]').prop('checked', true).trigger('change'); + return enterpriseTeamSetup(devEmail, $this); + }) + .catch(function(error) { + if (error.responseJSON) { + $this.nextAll('.login-error').html(error.responseJSON.message); + } + $this.html('Log in'); + $this.removeClass('disabled'); + Fliplet.Widget.autosize(); }); - - appStoreSubmission.data['fl-credentials'] = 'submission-' + appStoreSubmission.id; - - if(previousSubWithCredentials) { - cloneAppStoreCredentialsPromise = cloneCredentials(organizationID, previousSubWithCredentials.data['fl-credentials'], appStoreSubmission, true); - } } +}); - var esub = _.filter(submissions, function(submission) { - return submission.data.submissionType === "enterprise" && submission.platform === "ios"; +$('.log-out-enterprise').on('click', function() { + setCredentials(organizationID, enterpriseSubmission.id, { + email: null, + password: null, + teamId: null + }, false).then(function () { + enterpriseLoggedIn = false; + $('#fl-ent-appDevPass').prop('required', true); + $('.enterprise-logged-email').html(''); + $('.enterprise-login-details').removeClass('hidden'); + $('.enterprise-logged-in, .enterprise-more-options, .enterprise-teams').removeClass('show'); }); +}); - var completedEsub = _.filter(esub, function(submission) { - return submission.status === "completed"; - }); - //Get the Submission data from the first completed submission, it has certification values that are in use on the developer portal. - previousEnterpriseStoreSubmission = _.minBy(completedEsub, function(el) { - return el.id; - }); +$('[name="fl-ent-distribution"]').on('change', function() { + var value = $(this).val(); - esub = _.orderBy(esub, function(submission) { - return new Date(submission.createdAt).getTime(); - }, ['desc']); - checkSubmissionStatus("enterprise", esub); + $('#fl-ent-teams').prop('required',true); - enterpriseSubmission = _.maxBy(esub, function(el) { - return new Date(el.createdAt).getTime(); - }); + if (value === 'previous-file') { + if (enterpriseCertificateReplaced) { + $('.enterprise-previous-file-success').addClass('show'); + } - if (!enterpriseSubmission) { - enterpriseSubmission = {}; + $('.enterprise-generate-file, .enterprise-generate-file-success, .enterprise-upload-file').removeClass('show'); } - - var cloneEnterpriseCredentialsPromise = Promise.resolve(); - if (enterpriseSubmission.data && !enterpriseSubmission.data['fl-credentials']) { - - var prevSubCred = _.filter(esub, function(submission) { - return submission.data && submission.data['fl-credentials']; - }); - - var previousSubWithCredentials = _.maxBy(prevSubCred, function(el) { - return new Date(el.createdAt).getTime(); - }); - - enterpriseSubmission.data['fl-credentials'] = 'submission-' + enterpriseSubmission.id; - - if(previousSubWithCredentials) { - cloneEnterpriseCredentialsPromise = cloneCredentials(organizationID, previousSubWithCredentials.data['fl-credentials'], enterpriseSubmission, true); + if (value === 'generate-file') { + if (enterpriseCertificateCreated) { + $('.enterprise-generate-file-success').addClass('show'); + } else { + $('.enterprise-generate-file').addClass('show'); } + $('.enterprise-previous-file-success, .enterprise-upload-file').removeClass('show'); + $('#fl-ent-certificate').prop('required',false); } + if (value === 'upload-file') { + $('.enterprise-upload-file').addClass('show'); + $('.enterprise-previous-file-success, .enterprise-generate-file, .enterprise-generate-file-success').removeClass('show'); + $('#fl-ent-certificate').prop('required',true); + } + Fliplet.Widget.autosize(); +}); - var usub = _.filter(submissions, function(submission) { - return submission.data.submissionType === "unsigned" && submission.platform === "ios"; - }); - - usub = _.orderBy(usub, function(submission) { - return new Date(submission.createdAt).getTime(); - }, ['desc']); - checkSubmissionStatus("unsigned", usub); +$('#fl-ent-teams').on('change', function() { + var value = $(this).val(); + var teamName = value ? $('#fl-ent-teams').find(":selected").data('team-name') : ''; - usub = _.maxBy(usub, function(el) { - return new Date(el.createdAt).getTime(); - }); - unsignedSubmission = usub; + if (value !== '') { + $('.enterprise-more-options').addClass('show'); + $('.enterprise-generate-cert').removeClass('disabled'); + $('.enterprise-upload-certificate').removeClass('disabled'); + } else { + $('.enterprise-more-options').removeClass('show'); + $('.enterprise-generate-cert').addClass('disabled'); + $('.enterprise-upload-certificate').addClass('disabled'); + } - return cloneAppStoreCredentialsPromise.then(function () { - return cloneEnterpriseCredentialsPromise; - }).then(function () { - if (_.isEmpty(appStoreSubmission)) { - return Fliplet.App.Submissions.create({ - platform: 'ios', - data: { - submissionType: "appStore" - } - }) - .then(function(submission) { - appStoreSubmission = submission; - return Promise.resolve(); - }); - } + var devEmail = $('#fl-ent-appDevLogin').val(); + return refreshAppEnterpriseOptions(devEmail, value, teamName); +}); - return Promise.resolve(); - }).then(function () { - if (_.isEmpty(enterpriseSubmission)) { - return Fliplet.App.Submissions.create({ - platform: 'ios', - data: { - submissionType: "enterprise" - } - }) - .then(function(submission) { - enterpriseSubmission = submission; - return Promise.resolve(); - }); - } +$('.enterprise-generate-cert').on('click', function() { + var $this = $(this); + $(this).html('Generating...'); + $(this).addClass('disabled'); + $('.generate-error').html(''); // Cleans errors + var teamId = $('#fl-ent-teams').val(); + enterpriseTeamId = teamId; + var teamName = $('#fl-ent-teams').find(":selected").data('team-name'); - return Promise.resolve(); - }).then(function () { - if (_.isEmpty(unsignedSubmission)) { - return Fliplet.App.Submissions.create({ - platform: 'ios', - data: { - submissionType: "unsigned" - } + return setCredentials(organizationID, enterpriseSubmission.id, { + teamId: teamId, + teamName: teamName + }) + .then(function() { + return createCertificates({ + organizationId: organizationID, + submissionId: enterpriseSubmission.id, + inHouse: true }) - .then(function(submission) { - unsignedSubmission = submission; - return Promise.resolve(); - }); - } - - return Promise.resolve(); - }); -} - -function iosSubmissionChecker(submissions) { - var asub = _.filter(submissions, function(submission) { - return submission.data.submissionType === "appStore" && submission.platform === "ios"; - }); + .then(function(response) { + var p12Url = Fliplet.Env.get('apiUrl') + 'v1/organizations/' + organizationID + '/credentials/submission-' + enterpriseSubmission.id + '/download/p12' + enterpriseCertificateCreated = true; + $('.enterprise-generate-file-success').find('.enterprise-file-name-success').html(response.certificate.name); + $('.enterprise-generate-file-success').find('.enterprise-file-expire-success').html(moment(response.certificate.expiresAt).format('MMMM Do YYYY')); + $('.enterprise-generate-file-success').find('.enterprise-file-download-success').attr('href', p12Url); + $('.enterprise-generate-file').removeClass('show'); + $('.enterprise-generate-file-success').addClass('show'); + $this.html('Generate certificate'); + $this.removeClass('disabled'); + }); + }) + .catch(function(error) { + $this.html('Generate certificate'); + $this.removeClass('disabled'); + if (error.responseJSON.message) { + $('.generate-error').html(error.responseJSON.message); + } + }); +}); - var esub = _.filter(submissions, function(submission) { - return submission.data.submissionType === "enterprise" && submission.platform === "ios"; - }); +$('#fl-ent-certificate').on('change', function() { + enterpriseFileField = this; + var fileName = enterpriseFileField.value.replace(/\\/g, '/').replace(/.*\//, ''); - var usub = _.filter(submissions, function(submission) { - return submission.data.submissionType === "unsigned" && submission.platform === "ios"; - }); + if (enterpriseFileField.files && enterpriseFileField.files[0]) { + $('#fl-ent-certificate-label').val(fileName); + } +}); - // Ordering - asub = _.orderBy(asub, function(submission) { - return new Date(submission.createdAt).getTime(); - }, ['desc']); - esub = _.orderBy(esub, function(submission) { - return new Date(submission.createdAt).getTime(); - }, ['desc']); - usub = _.orderBy(usub, function(submission) { - return new Date(submission.createdAt).getTime(); - }, ['desc']); +$('#fl-ent-certificate-manual-details').on('change', function() { + enterpriseFileFieldManual = this; + var fileName = enterpriseFileFieldManual.value.replace(/\\/g, '/').replace(/.*\//, ''); - checkSubmissionStatus("appStore", asub); - checkSubmissionStatus("enterprise", esub); - checkSubmissionStatus("unsigned", usub); -} + if (enterpriseFileFieldManual.files && enterpriseFileFieldManual.files[0]) { + $('#fl-ent-certificate-manual-details-label').val(fileName); + } +}); -function getSubmissions() { - return Fliplet.App.Submissions.get(); -} +$('#fl-ent-mobileprovision-manual-details').on('change', function() { + enterpriseFileProvisionFieldManual = this; + var fileName = enterpriseFileProvisionFieldManual.value.replace(/\\/g, '/').replace(/.*\//, ''); -function initialLoad(initial, timeout) { - if (!initial) { - initLoad = setTimeout(function() { - getSubmissions() - .then(function(submissions) { - iosSubmissionChecker(submissions); - initialLoad(false, 15000); - }); - }, timeout); - } else { - getSubmissions() - .then(function(submissions) { + if (enterpriseFileProvisionFieldManual.files && enterpriseFileProvisionFieldManual.files[0]) { + $('#fl-ent-mobileprovision-manual-details-label').val(fileName); + } +}); - if (!submissions.length) { - return Promise.all([ - Fliplet.App.Submissions.create({ - platform: 'ios', - data: { - submissionType: "appStore" - } - }) - .then(function(submission) { - appStoreSubmission = submission; - }), - Fliplet.App.Submissions.create({ - platform: 'ios', - data: { - submissionType: "unsigned" - } - }) - .then(function(submission) { - unsignedSubmission = submission; - }), - Fliplet.App.Submissions.create({ - platform: 'ios', - data: { - submissionType: "enterprise" - } - }) - .then(function(submission) { - enterpriseSubmission = submission; - }) - ]); - } +$('.enterprise-replace-cert').on('click', function() { + var $this = $(this); + $(this).html('Replacing...'); + $(this).addClass('disabled'); + $('.replace-error').html(''); // Cleans errors + var teamId = enterprisePreviousCredential ? enterprisePreviousCredential.teamId : ''; + enterpriseTeamId = teamId; + var teamName = enterprisePreviousCredential ? enterprisePreviousCredential.teamName : ''; - return Fliplet.API.request({ - cache: true, - url: 'v1/user' - }) - .then(function(user) { - userInfo = user; - return submissionChecker(submissions); - }); - }) + if (enterprisePreviousCredential.certificate && enterprisePreviousCredential.certificate.id) { + return revokeCertificate(organizationID, enterpriseSubmission.id, enterprisePreviousCredential.certificate.id) .then(function() { - // Fliplet.Env.get('appId') - // Fliplet.Env.get('appName') - // Fliplet.Env.get('appSettings') - - return Promise.all([ - Fliplet.API.request({ - method: 'GET', - url: 'v1/apps/' + Fliplet.Env.get('appId') - }) - .then(function(result) { - appName = result.app.name; - appIcon = result.app.icon; - appSettings = result.app.settings; - }), - Fliplet.API.request({ - method: 'GET', - url: 'v1/organizations/' + Fliplet.Env.get('organizationId') - }) - .then(function(org) { - organizationName = org.name; + return setCredentials(organizationID, enterpriseSubmission.id, { + teamId: teamId, + teamName: teamName }) - ]); - }) - .then(function() { - if (appSettings.folderStructure) { - var structure = []; - hasFolders = true; - var appleOnly = _.filter(appSettings.folderStructure, function(obj) { - return obj.platform === 'apple'; - }); - - return Promise.all(appleOnly.map(function(obj) { - return Fliplet.Media.Folders.get({folderId: obj.folderId}) - .then(function(result) { - var tempObject = { - type: obj.type, - folderContent: result - } - - structure.push(tempObject); - return Promise.resolve(structure); - }); - })) .then(function() { - structure.forEach(function(el, idx) { - if (el.type === 'mobile') { - screenShotsMobile = el.folderContent.files - } - if (el.type === 'tablet') { - screenShotsTablet = el.folderContent.files - } - }); + return createCertificates({ + organiazationId: organizationID, + submissionId: enterpriseSubmission.id, + inHouse: true + }) + .then(function(response) { + var p12Url = Fliplet.Env.get('apiUrl') + 'v1/organizations/' + organizationID + '/credentials/submission-' + enterpriseSubmission.id + '/download/p12' + enterpriseCertificateReplaced = true; + $('.enterprise-previous-file-success').find('.enterprise-file-name-success').html(response.certificate.name); + $('.enterprise-previous-file-success').find('.enterprise-file-expire-success').html(moment(response.certificate.expiresAt).format('MMMM Do YYYY')); + $('.enterprise-previous-file-success').find('.enterprise-file-download-success').attr('href', p12Url); + $('.enterprise-previous-file-success').addClass('show'); + $this.html('Replace certificate'); + $this.removeClass('disabled'); + }); }); - } else { - hasFolders = false; - return; - } - }) - .then(function() { - return Fliplet.API.request({ - method: 'GET', - url: 'v1/widget-instances/com.fliplet.push-notifications?appId=' + Fliplet.Env.get('appId') - }); }) - .then(function(response) { - if (response.widgetInstance.settings && response.widgetInstance.settings) { - notificationSettings = response.widgetInstance.settings; - } else { - notificationSettings = {}; + .catch(function(error) { + $this.html('Replace certificate'); + $this.removeClass('disabled'); + if (error.responseJSON.message) { + $('.replace-error').html(error.responseJSON.message); } - - init(); - initialLoad(false, 5000); }); + } else { + $this.html('Replace certificate'); + $this.removeClass('disabled'); + $('.replace-error').html("We could not replace the certificate.\nPlease log into your https://developer.apple.com/account/ and revoke the certificate and create a new one using Fliplet."); } -} +}); -// Start -initLoad = initialLoad(true, 0); +$('.ent-enter-manually').on('click', function() { + $('.enterprise-login-details').addClass('hidden'); + $('.enterprise-manual-details').addClass('show'); + enterpriseManual = true; -// @TODO Move function -function prompt2FACode() { - // @TODO Update Fliplet.Modal in fliplet-api for simpler call - return Fliplet.Modal.prompt({ - title: 'Please enter the verification code to verify your login' - }).then(function (code) { - if (code === null) { - return null; - } + $('#fl-ent-appDevLogin').prop('required', false); + $('#fl-ent-appDevPass').prop('required', false); + $('#fl-ent-teams').prop('required',false); - if (code === '') { - return Fliplet.Modal.alert({ - message: 'You must enter the verification code to log in' - }).then(function () { - return prompt2FACode(); - }); - } + $('#fl-ent-teamName').prop('required', true); + $('#fl-ent-teamId').prop('required', true); + $('#fl-ent-certificate-manual-details').prop('required', true); + $('#fl-ent-mobileprovision-manual-details').prop('required', true); +}); - return code; +$('.enterprise-back-login').on('click', function() { + $('.enterprise-login-details').removeClass('hidden'); + $('.enterprise-manual-details').removeClass('show'); + enterpriseManual = false; + + $('#fl-ent-appDevLogin').prop('required', true); + $('#fl-ent-appDevPass').prop('required', true); + $('#fl-ent-teams').prop('required',true); + + $('#fl-ent-teamName').prop('required', false); + $('#fl-ent-teamId').prop('required', false); + $('#fl-ent-certificate-manual-details').prop('required', false); + $('#fl-ent-mobileprovision-manual-details').prop('required', false); +}); +/**/ + +$(document).on('click', '[data-cancel-build-id]', function() { + var buildId = $(this).data('cancel-build-id'); + + Fliplet.API.request({ + method: 'DELETE', + url: 'v1/apps/' + Fliplet.Env.get('appId') + '/submissions/' + buildId + }) + .then(function() { + clearTimeout(initLoad); + initialLoad(false, 0); + }) +}); + +$('.browse-files').on('click', function(e) { + e.preventDefault(); + + Fliplet.Studio.emit('overlay', { + name: 'widget', + options: { + size: 'large', + package: 'com.fliplet.file-manager', + title: 'File Manager', + classes: 'data-source-overlay', + data: { + context: 'overlay', + appId: Fliplet.Env.get('appId') + } + } }); -} +}); + +/* INIT */ +$('#appStoreConfiguration, #enterpriseConfiguration, #unsignedConfiguration').validator().off('change.bs.validator focusout.bs.validator'); +$('[name="submissionType"][value="appStore"]').prop('checked', true).trigger('change'); + +// Start +initLoad = initialLoad(true, 0); // Listen for 2FA code when requested socket.on('aab.apple.login.2fa', function (data) { From 2dda939ea68f859f13907cbc65f014e54ee0812a Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Wed, 20 Feb 2019 11:53:23 +0000 Subject: [PATCH 095/318] Prevents form submission when logging in to Apple --- js/interface.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/js/interface.js b/js/interface.js index 32aad57..299bdd7 100644 --- a/js/interface.js +++ b/js/interface.js @@ -2128,6 +2128,12 @@ $('#appStoreConfiguration, #enterpriseConfiguration, #unsignedConfiguration').on }); $('#appStoreConfiguration').validator().on('submit', function(event) { + if (_.includes(['fl-store-appDevLogin', 'fl-store-appDevPass'], document.activeElement.id)) { + // User submitted app store login form + $('.login-appStore-button').trigger('click'); + return; + } + if (event.isDefaultPrevented()) { // Gives time to Validator to apply classes setTimeout(checkGroupErrors, 0); @@ -2205,6 +2211,12 @@ $('#appStoreConfiguration').validator().on('submit', function(event) { }); $('#enterpriseConfiguration').validator().on('submit', function(event) { + if (_.includes(['fl-ent-appDevLogin', 'fl-ent-appDevPass'], document.activeElement.id)) { + // User submitted enterprise login form + $('.login-enterprise-button').trigger('click'); + return; + } + if (event.isDefaultPrevented()) { // Gives time to Validator to apply classes setTimeout(checkGroupErrors, 0); From a008a70e7489ecf836e933a7959307d8e5f62b38 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Wed, 20 Feb 2019 11:53:35 +0000 Subject: [PATCH 096/318] Indenting --- js/interface.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/js/interface.js b/js/interface.js index 299bdd7..7b69da5 100644 --- a/js/interface.js +++ b/js/interface.js @@ -2383,18 +2383,18 @@ $('.login-appStore-button').on('click', function() { email: devEmail, password: devPass }) - .then(function() { - return appStoreTeamSetup(devEmail, $this); - }) - .catch(function(error) { - console.log(error); - if (error.responseJSON) { - $this.nextAll('.login-error').html(error.responseJSON.message); - } - $this.html('Log in'); - $this.removeClass('disabled'); - Fliplet.Widget.autosize(); - }); + .then(function() { + return appStoreTeamSetup(devEmail, $this); + }) + .catch(function(error) { + console.log(error); + if (error.responseJSON) { + $this.nextAll('.login-error').html(error.responseJSON.message); + } + $this.html('Log in'); + $this.removeClass('disabled'); + Fliplet.Widget.autosize(); + }); } }); From 3a0b91c9b2ba26128c32a7e5a521d81efe1ebbe8 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Wed, 20 Feb 2019 11:53:59 +0000 Subject: [PATCH 097/318] Adds placeholder functions for handling 2FA success/fail/cancel --- js/interface.js | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/js/interface.js b/js/interface.js index 7b69da5..1a08daf 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1967,7 +1967,7 @@ function initialLoad(initial, timeout) { } } -function prompt2FACode() { +function prompt2FA() { // @TODO Update Fliplet.Modal in fliplet-api for simpler call return Fliplet.Modal.prompt({ title: 'Please enter the verification code to verify your login' @@ -1980,7 +1980,7 @@ function prompt2FACode() { return Fliplet.Modal.alert({ message: 'You must enter the verification code to log in' }).then(function () { - return prompt2FACode(); + return prompt2FA(); }); } @@ -1988,6 +1988,18 @@ function prompt2FACode() { }); } +function on2FASuccess(data) { + console.log('2FA success', data); +} + +function on2FAFail(data) { + console.log('2FA fail', data); +} + +function on2FACancel() { + +} + /* ATTACH LISTENERS */ $('[name="fl-store-screenshots"]').on('change', function() { var value = $(this).val(); @@ -2861,24 +2873,18 @@ initLoad = initialLoad(true, 0); // Listen for 2FA code when requested socket.on('aab.apple.login.2fa', function (data) { // Ask user for code - prompt2FACode().then(function (code) { + prompt2FA().then(function (code) { if (code === null) { - socket.to(data.clientId).emit('aab.apple.login.2fa.cancel'); + on2FACancel(); return; } - // Notify requester with the code - // @Question What happens when 2FA succeeds/fails? socket.to(data.clientId).emit('aab.apple.login.2fa.code', code); }); }); // Listen for a 2FA code successfully entered -socket.on('aab.apple.login.2fa.success', function () { - console.log('2FA code is correct'); -}); +socket.on('aab.apple.login.2fa.success', on2FASuccess); // Listen for a wrong 2FA code -socket.on('aab.apple.login.2fa.failure', function () { - console.log('2FA code is wrong'); -}); \ No newline at end of file +socket.on('aab.apple.login.2fa.failure', on2FAFail); \ No newline at end of file From 15ecbaf52526c0c55f3c1eae924d4612e6c3e8d4 Mon Sep 17 00:00:00 2001 From: Nicholas Valbusa Date: Wed, 20 Feb 2019 13:42:32 +0100 Subject: [PATCH 098/318] skeleton for selecting devices --- js/interface.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/js/interface.js b/js/interface.js index 1a08daf..f8528ce 100644 --- a/js/interface.js +++ b/js/interface.js @@ -2883,6 +2883,15 @@ socket.on('aab.apple.login.2fa', function (data) { }); }); +socket.on('aab.apple.login.2fa.devices', function (data) { + console.log('Devices', data.devices); + + // @TODO: select device + // Selected index should start from 1, not 0 + + socket.to(data.clientId).emit('aab.apple.login.2fa.device', 1); +}); + // Listen for a 2FA code successfully entered socket.on('aab.apple.login.2fa.success', on2FASuccess); From 6d6f38774edf15c6e563d6450c28841ecf4140b3 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Wed, 20 Feb 2019 12:54:46 +0000 Subject: [PATCH 099/318] Adds method for selecting 2FA methods --- js/interface.js | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/js/interface.js b/js/interface.js index f8528ce..541179f 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1967,8 +1967,38 @@ function initialLoad(initial, timeout) { } } +function select2FAMethod(data) { + data = data || {}; + + var options = _.map(data.devices, function (value, index) { + return { + text: value, + value: index + 1 + }; + }); + + return Fliplet.Modal.prompt({ + title: 'Please select a device to verify your identity', + inputType: 'select', + inputOptions: options + }).then(function (selection) { + if (selection === null) { + return null; + } + + if (selection === '') { + return Fliplet.Modal.alert({ + message: 'You must select a device to verify your identity' + }).then(function () { + return select2FAMethod(); + }); + } + + return selection; + }); +} + function prompt2FA() { - // @TODO Update Fliplet.Modal in fliplet-api for simpler call return Fliplet.Modal.prompt({ title: 'Please enter the verification code to verify your login' }).then(function (code) { @@ -2886,10 +2916,14 @@ socket.on('aab.apple.login.2fa', function (data) { socket.on('aab.apple.login.2fa.devices', function (data) { console.log('Devices', data.devices); - // @TODO: select device - // Selected index should start from 1, not 0 + select2FAMethod(data).then(function (selection) { + if (selection === null) { + on2FACancel(); + return; + } - socket.to(data.clientId).emit('aab.apple.login.2fa.device', 1); + socket.to(data.clientId).emit('aab.apple.login.2fa.device', selection); + }); }); // Listen for a 2FA code successfully entered From 7d6ada06ad0aad6333b612150d5b94051590dd78 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Wed, 20 Feb 2019 12:58:13 +0000 Subject: [PATCH 100/318] Ensures 2FA method selection is called correctly --- js/interface.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/interface.js b/js/interface.js index 541179f..438d011 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1990,7 +1990,7 @@ function select2FAMethod(data) { return Fliplet.Modal.alert({ message: 'You must select a device to verify your identity' }).then(function () { - return select2FAMethod(); + return select2FAMethod(data); }); } From c613bd22b1e032a0fe5c0bb3ac394b2d00253662 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Wed, 20 Feb 2019 13:46:49 +0000 Subject: [PATCH 101/318] Uniforms how errors are parsed, displayed and logged --- js/interface.js | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/js/interface.js b/js/interface.js index 438d011..8f909d4 100644 --- a/js/interface.js +++ b/js/interface.js @@ -2430,9 +2430,7 @@ $('.login-appStore-button').on('click', function() { }) .catch(function(error) { console.log(error); - if (error.responseJSON) { - $this.nextAll('.login-error').html(error.responseJSON.message); - } + $this.nextAll('.login-error').html(Fliplet.parseError(error)); $this.html('Log in'); $this.removeClass('disabled'); Fliplet.Widget.autosize(); @@ -2537,9 +2535,8 @@ $('.appStore-generate-cert').on('click', function() { .catch(function(error) { $this.html('Generate certificate'); $this.removeClass('disabled'); - if (error.responseJSON.message) { - $('.generate-error').html(error.responseJSON.message); - } + console.log(error); + $('.generate-error').html(Fliplet.parseError(error)); }); }); @@ -2588,9 +2585,8 @@ $('.appStore-replace-cert').on('click', function() { .catch(function(error) { $this.html('Replace certificate'); $this.removeClass('disabled'); - if (error.responseJSON.message) { - $('.replace-error').html(error.responseJSON.message); - } + console.log(error); + $('.replace-error').html(Fliplet.parseError(error)); }); } else { $this.html('Replace certificate'); @@ -2645,9 +2641,8 @@ $('.login-enterprise-button').on('click', function() { return enterpriseTeamSetup(devEmail, $this); }) .catch(function(error) { - if (error.responseJSON) { - $this.nextAll('.login-error').html(error.responseJSON.message); - } + console.log(error); + $this.nextAll('.login-error').html(Fliplet.parseError(error)); $this.html('Log in'); $this.removeClass('disabled'); Fliplet.Widget.autosize(); @@ -2750,9 +2745,8 @@ $('.enterprise-generate-cert').on('click', function() { .catch(function(error) { $this.html('Generate certificate'); $this.removeClass('disabled'); - if (error.responseJSON.message) { - $('.generate-error').html(error.responseJSON.message); - } + console.log(error); + $('.generate-error').html(Fliplet.parseError(error)); }); }); @@ -2820,9 +2814,8 @@ $('.enterprise-replace-cert').on('click', function() { .catch(function(error) { $this.html('Replace certificate'); $this.removeClass('disabled'); - if (error.responseJSON.message) { - $('.replace-error').html(error.responseJSON.message); - } + console.log(error); + $('.replace-error').html(Fliplet.parseError(error)); }); } else { $this.html('Replace certificate'); From 2cc2de729ff236cbe16473eb60a1c0380e840885 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Wed, 20 Feb 2019 14:00:23 +0000 Subject: [PATCH 102/318] Indentation adjustments --- js/interface.js | 68 ++++++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/js/interface.js b/js/interface.js index 8f909d4..70e0111 100644 --- a/js/interface.js +++ b/js/interface.js @@ -688,13 +688,13 @@ function requestBuild(origin, submission) { // Check which type of certificate was given if (origin === "appStore" && appStoreSubmission.data['fl-store-distribution'] === 'previous-file' && appStorePreviousCredential) { return setCredentials(organizationID, appStoreSubmission.id, { - teamId: appStorePreviousCredential.teamId, - teamName: appStorePreviousCredential.teamName, - certSigningRequest: appStorePreviousCredential.certSigningRequest, - p12: appStorePreviousCredential.p12, - certificate: appStorePreviousCredential.certificate, - content: appStorePreviousCredential.content - }) + teamId: appStorePreviousCredential.teamId, + teamName: appStorePreviousCredential.teamName, + certSigningRequest: appStorePreviousCredential.certSigningRequest, + p12: appStorePreviousCredential.p12, + certificate: appStorePreviousCredential.certificate, + content: appStorePreviousCredential.content + }) .then(function() { submissionBuild(newSubmission, origin); }); @@ -725,13 +725,13 @@ function requestBuild(origin, submission) { if (origin === "enterprise" && enterpriseSubmission.data['fl-ent-distribution'] === 'previous-file' && enterprisePreviousCredential) { return setCredentials(organizationID, enterpriseSubmission.id, { - teamId: enterprisePreviousCredential.teamId, - teamName: enterprisePreviousCredential.teamName, - certSigningRequest: enterprisePreviousCredential.certSigningRequest, - p12: enterprisePreviousCredential.p12, - certificate: enterprisePreviousCredential.certificate, - content: enterprisePreviousCredential.content - }) + teamId: enterprisePreviousCredential.teamId, + teamName: enterprisePreviousCredential.teamName, + certSigningRequest: enterprisePreviousCredential.certSigningRequest, + p12: enterprisePreviousCredential.p12, + certificate: enterprisePreviousCredential.certificate, + content: enterprisePreviousCredential.content + }) .then(function() { submissionBuild(newSubmission, origin); }); @@ -750,9 +750,9 @@ function requestBuild(origin, submission) { var teamName = $('#fl-ent-teams').find(":selected").data('team-name'); return setCredentials(organizationID, enterpriseSubmission.id, { - teamId: teamId, - teamName: teamName - }) + teamId: teamId, + teamName: teamName + }) .then(function() { return setCertificateP12(organizationID, enterpriseSubmission.id, formData) }) @@ -775,13 +775,13 @@ function requestBuild(origin, submission) { // Check which type of certificate was given if (origin === "appStore" && appStoreSubmission.data['fl-store-distribution'] === 'previous-file' && appStorePreviousCredential) { return setCredentials(organizationID, appStoreSubmission.id, { - teamId: appStorePreviousCredential.teamId, - teamName: appStorePreviousCredential.teamName, - certSigningRequest: appStorePreviousCredential.certSigningRequest, - p12: appStorePreviousCredential.p12, - certificate: appStorePreviousCredential.certificate, - content: appStorePreviousCredential.content - }) + teamId: appStorePreviousCredential.teamId, + teamName: appStorePreviousCredential.teamName, + certSigningRequest: appStorePreviousCredential.certSigningRequest, + p12: appStorePreviousCredential.p12, + certificate: appStorePreviousCredential.certificate, + content: appStorePreviousCredential.content + }) .then(function() { submissionBuild(submission, origin); }); @@ -812,13 +812,13 @@ function requestBuild(origin, submission) { if (origin === "enterprise" && enterpriseSubmission.data['fl-ent-distribution'] === 'previous-file' && enterprisePreviousCredential) { return setCredentials(organizationID, enterpriseSubmission.id, { - teamId: enterprisePreviousCredential.teamId, - teamName: enterprisePreviousCredential.teamName, - certSigningRequest: enterprisePreviousCredential.certSigningRequest, - p12: enterprisePreviousCredential.p12, - certificate: enterprisePreviousCredential.certificate, - content: enterprisePreviousCredential.content - }) + teamId: enterprisePreviousCredential.teamId, + teamName: enterprisePreviousCredential.teamName, + certSigningRequest: enterprisePreviousCredential.certSigningRequest, + p12: enterprisePreviousCredential.p12, + certificate: enterprisePreviousCredential.certificate, + content: enterprisePreviousCredential.content + }) .then(function() { submissionBuild(submission, origin); }); @@ -2790,9 +2790,9 @@ $('.enterprise-replace-cert').on('click', function() { return revokeCertificate(organizationID, enterpriseSubmission.id, enterprisePreviousCredential.certificate.id) .then(function() { return setCredentials(organizationID, enterpriseSubmission.id, { - teamId: teamId, - teamName: teamName - }) + teamId: teamId, + teamName: teamName + }) .then(function() { return createCertificates({ organiazationId: organizationID, From 50454317efbebed0fb0cb79af13c5b3e1540a9c7 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Wed, 20 Feb 2019 14:00:51 +0000 Subject: [PATCH 103/318] Removes unnecesary Promise.then() clause --- js/interface.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/js/interface.js b/js/interface.js index 70e0111..098ca9a 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1120,14 +1120,12 @@ function cloneCredentials(organizationId, credentialKey, submission, saveData) { function setCredentials(organizationId, id, data, verify) { verify = typeof verify === 'undefined' ? true : verify; + return Fliplet.API.request({ method: 'PUT', url: 'v1/organizations/' + organizationId + '/credentials/submission-' + id + '?verify=' + verify, data: data - }) - .then(function() { - return Promise.resolve(); - }) + }); } function getTeams(organizationId, id, isItunes) { From 7e2c10dee0e297bf236182a7b1d6ac121a7d65b8 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Wed, 20 Feb 2019 14:02:09 +0000 Subject: [PATCH 104/318] Cleanup --- js/interface.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/js/interface.js b/js/interface.js index 098ca9a..892ae2d 100644 --- a/js/interface.js +++ b/js/interface.js @@ -442,7 +442,6 @@ function enterpriseTeamSetup(devEmail, loginButton) { } function loadUnsignedData() { - $('#unsignedConfiguration [name]').each(function(i, el) { var name = $(el).attr("name"); @@ -2905,8 +2904,6 @@ socket.on('aab.apple.login.2fa', function (data) { }); socket.on('aab.apple.login.2fa.devices', function (data) { - console.log('Devices', data.devices); - select2FAMethod(data).then(function (selection) { if (selection === null) { on2FACancel(); From 049ebf27a49ced84209d0c0ccf4c3b5fb6856e3c Mon Sep 17 00:00:00 2001 From: Nicholas Valbusa Date: Wed, 20 Feb 2019 17:05:39 +0100 Subject: [PATCH 105/318] support for long polling --- js/interface.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/js/interface.js b/js/interface.js index 892ae2d..b5a10c7 100644 --- a/js/interface.js +++ b/js/interface.js @@ -40,7 +40,11 @@ var screenShotsMobile = []; var screenShotsTablet = []; var haveScreenshots = false; var screenshotValidationNotRequired = false; -var socket = Fliplet.Socket({ login: true }); + +var socket = Fliplet.Socket({ + transports: ['polling'], // avoid being blocked by AdBlockers + login: true +}); /* FUNCTIONS */ String.prototype.toCamelCase = function() { From e10c578c9876531da9966d4ff6a7c93206224029 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Wed, 20 Feb 2019 16:09:17 +0000 Subject: [PATCH 106/318] Cleans up socket implementation to remove unused handlers --- js/interface.js | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/js/interface.js b/js/interface.js index b5a10c7..4c9120d 100644 --- a/js/interface.js +++ b/js/interface.js @@ -2019,18 +2019,6 @@ function prompt2FA() { }); } -function on2FASuccess(data) { - console.log('2FA success', data); -} - -function on2FAFail(data) { - console.log('2FA fail', data); -} - -function on2FACancel() { - -} - /* ATTACH LISTENERS */ $('[name="fl-store-screenshots"]').on('change', function() { var value = $(this).val(); @@ -2899,7 +2887,7 @@ socket.on('aab.apple.login.2fa', function (data) { // Ask user for code prompt2FA().then(function (code) { if (code === null) { - on2FACancel(); + socket.to(data.clientId).emit('aab.apple.login.2fa.cancel'); return; } @@ -2910,16 +2898,10 @@ socket.on('aab.apple.login.2fa', function (data) { socket.on('aab.apple.login.2fa.devices', function (data) { select2FAMethod(data).then(function (selection) { if (selection === null) { - on2FACancel(); + socket.to(data.clientId).emit('aab.apple.login.2fa.cancel'); return; } socket.to(data.clientId).emit('aab.apple.login.2fa.device', selection); }); }); - -// Listen for a 2FA code successfully entered -socket.on('aab.apple.login.2fa.success', on2FASuccess); - -// Listen for a wrong 2FA code -socket.on('aab.apple.login.2fa.failure', on2FAFail); \ No newline at end of file From d8ad76633bc49655bda06b8250adda2ba7b6f67c Mon Sep 17 00:00:00 2001 From: Nicholas Valbusa Date: Wed, 20 Feb 2019 17:19:01 +0100 Subject: [PATCH 107/318] show error on publish error --- js/interface.js | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/js/interface.js b/js/interface.js index cde0bf1..f7fa674 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1714,9 +1714,14 @@ $('#appStoreConfiguration').validator().on('submit', function(event) { }); } } else { + var initialHtml = $('.button-appStore-request').html(); $('.button-appStore-request').html('Please wait '); $('.button-appStore-request').prop('disabled', true); - publishApp('appStore'); + + publishApp('appStore').then(function () { + $('.button-appStore-request').html(initialHtml); + $('.button-appStore-request').prop('disabled', false); + }); } // Gives time to Validator to apply classes @@ -1783,9 +1788,14 @@ $('#enterpriseConfiguration').validator().on('submit', function(event) { }); } } else { + var initialHtml = $('.button-enterprise-request').html(); $('.button-enterprise-request').html('Please wait '); $('.button-enterprise-request').prop('disabled', true); - publishApp('enterprise'); + + publishApp('enterprise').catch(function () { + $('.button-enterprise-request').html(initialHtml); + $('.button-enterprise-request').prop('disabled', false); + }); } // Gives time to Validator to apply classes @@ -1827,9 +1837,14 @@ $('#unsignedConfiguration').validator().on('submit', function(event) { }); } } else { + var initialHtml = $('.button-unsigned-request').html(); $('.button-unsigned-request').html('Please wait '); $('.button-unsigned-request').prop('disabled', true); - publishApp('unsigned'); + + publishApp('unsigned').then(function () { + $('.button-unsigned-request').html(initialHtml); + $('.button-unsigned-request').prop('disabled', false); + }); } // Gives time to Validator to apply classes @@ -2370,7 +2385,8 @@ function publishApp(context) { changelog: 'Initial version' } }; - Fliplet.API.request({ + + return Fliplet.API.request({ method: 'POST', url: 'v1/apps/' + Fliplet.Env.get('appId') + '/publish', data: options @@ -2397,6 +2413,9 @@ function publishApp(context) { default: break; } + }).catch(function (err) { + Fliplet.Modal.alert({ message: Fliplet.parseError(err) }); + return Promise.reject(err); }); } From 510f8d4ad007efe06d5d41af8c6b46c3ddb6719a Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Wed, 20 Feb 2019 17:07:07 +0000 Subject: [PATCH 108/318] Message update for 2FA prompt --- js/interface.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/js/interface.js b/js/interface.js index 4c9120d..e0e57af 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1979,7 +1979,7 @@ function select2FAMethod(data) { }); return Fliplet.Modal.prompt({ - title: 'Please select a device to verify your identity', + title: 'Your Apple ID is protected with two-step verification. Choose a trusted device to receive a verification code.', inputType: 'select', inputOptions: options }).then(function (selection) { @@ -1989,7 +1989,7 @@ function select2FAMethod(data) { if (selection === '') { return Fliplet.Modal.alert({ - message: 'You must select a device to verify your identity' + message: 'You must select a device to continue.' }).then(function () { return select2FAMethod(data); }); @@ -1999,9 +1999,9 @@ function select2FAMethod(data) { }); } -function prompt2FA() { +function prompt2FA(data) { return Fliplet.Modal.prompt({ - title: 'Please enter the verification code to verify your login' + title: 'A message with a verification code has been sent to your devices. Please enter the code to continue.' }).then(function (code) { if (code === null) { return null; @@ -2009,9 +2009,9 @@ function prompt2FA() { if (code === '') { return Fliplet.Modal.alert({ - message: 'You must enter the verification code to log in' + message: 'You must enter the verification code to continue.' }).then(function () { - return prompt2FA(); + return prompt2FA(data); }); } @@ -2885,7 +2885,7 @@ initLoad = initialLoad(true, 0); // Listen for 2FA code when requested socket.on('aab.apple.login.2fa', function (data) { // Ask user for code - prompt2FA().then(function (code) { + prompt2FA(data).then(function (code) { if (code === null) { socket.to(data.clientId).emit('aab.apple.login.2fa.cancel'); return; From 810e48c72785775000b3559abc2bb6192bed1291 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Wed, 20 Feb 2019 17:07:43 +0000 Subject: [PATCH 109/318] Prompt message update --- js/interface.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/interface.js b/js/interface.js index e0e57af..ea3871e 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1989,7 +1989,7 @@ function select2FAMethod(data) { if (selection === '') { return Fliplet.Modal.alert({ - message: 'You must select a device to continue.' + message: 'You must choose a device to continue.' }).then(function () { return select2FAMethod(data); }); From ee970e5c1874d8a90999fc28ffde2f0a702475eb Mon Sep 17 00:00:00 2001 From: Nicholas Valbusa Date: Wed, 20 Feb 2019 18:26:47 +0100 Subject: [PATCH 110/318] fixes --- js/interface.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/js/interface.js b/js/interface.js index f7fa674..a62ef32 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1718,7 +1718,7 @@ $('#appStoreConfiguration').validator().on('submit', function(event) { $('.button-appStore-request').html('Please wait '); $('.button-appStore-request').prop('disabled', true); - publishApp('appStore').then(function () { + publishApp('appStore').catch(function () { $('.button-appStore-request').html(initialHtml); $('.button-appStore-request').prop('disabled', false); }); @@ -1841,7 +1841,7 @@ $('#unsignedConfiguration').validator().on('submit', function(event) { $('.button-unsigned-request').html('Please wait '); $('.button-unsigned-request').prop('disabled', true); - publishApp('unsigned').then(function () { + publishApp('unsigned').catch(function () { $('.button-unsigned-request').html(initialHtml); $('.button-unsigned-request').prop('disabled', false); }); @@ -2833,6 +2833,11 @@ function initialLoad(initial, timeout) { notificationSettings = {}; } + init(); + initialLoad(false, 5000); + }).catch(function (err) { + console.log('Error initialising AAB', err); + init(); initialLoad(false, 5000); }); From a310be0daffde55dc9ef9dae4fc08b424847e8f0 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Wed, 20 Feb 2019 17:57:52 +0000 Subject: [PATCH 111/318] Cleanup --- js/interface.js | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/js/interface.js b/js/interface.js index ea3871e..dec2fa9 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1968,7 +1968,7 @@ function initialLoad(initial, timeout) { } } -function select2FAMethod(data) { +function select2FADevice(data) { data = data || {}; var options = _.map(data.devices, function (value, index) { @@ -1991,7 +1991,7 @@ function select2FAMethod(data) { return Fliplet.Modal.alert({ message: 'You must choose a device to continue.' }).then(function () { - return select2FAMethod(data); + return select2FADevice(data); }); } @@ -1999,9 +1999,9 @@ function select2FAMethod(data) { }); } -function prompt2FA(data) { +function prompt2FA() { return Fliplet.Modal.prompt({ - title: 'A message with a verification code has been sent to your devices. Please enter the code to continue.' + title: 'A message with a verification code has been sent to your devices. Please enter the code to continue.

    If you are not certain which devices to check, please contact your Apple account administrator or IT team.' }).then(function (code) { if (code === null) { return null; @@ -2011,7 +2011,7 @@ function prompt2FA(data) { return Fliplet.Modal.alert({ message: 'You must enter the verification code to continue.' }).then(function () { - return prompt2FA(data); + return prompt2FA(); }); } @@ -2883,25 +2883,30 @@ $('[name="submissionType"][value="appStore"]').prop('checked', true).trigger('ch initLoad = initialLoad(true, 0); // Listen for 2FA code when requested -socket.on('aab.apple.login.2fa', function (data) { +socket.on('aab.apple.login.2fa', function () { // Ask user for code - prompt2FA(data).then(function (code) { + prompt2FA().then(function (code) { if (code === null) { socket.to(data.clientId).emit('aab.apple.login.2fa.cancel'); return; } socket.to(data.clientId).emit('aab.apple.login.2fa.code', code); + }).catch(function () { + socket.to(data.clientId).emit('aab.apple.login.2fa.cancel'); }); }); socket.on('aab.apple.login.2fa.devices', function (data) { - select2FAMethod(data).then(function (selection) { + // Ask user to select device + select2FADevice(data).then(function (selection) { if (selection === null) { socket.to(data.clientId).emit('aab.apple.login.2fa.cancel'); return; } socket.to(data.clientId).emit('aab.apple.login.2fa.device', selection); + }).catch(function () { + socket.to(data.clientId).emit('aab.apple.login.2fa.cancel'); }); }); From 41cbdff585dd84ee79b070a2b586929e267ea67c Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Wed, 20 Feb 2019 18:29:06 +0000 Subject: [PATCH 112/318] Manually merges changes from master --- js/interface.js | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/js/interface.js b/js/interface.js index dec2fa9..766591d 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1518,7 +1518,8 @@ function publishApp(context) { changelog: 'Initial version' } }; - Fliplet.API.request({ + + return Fliplet.API.request({ method: 'POST', url: 'v1/apps/' + Fliplet.Env.get('appId') + '/publish', data: options @@ -1545,6 +1546,9 @@ function publishApp(context) { default: break; } + }).catch(function (err) { + Fliplet.Modal.alert({ message: Fliplet.parseError(err) }); + return Promise.reject(err); }); } @@ -2232,9 +2236,14 @@ $('#appStoreConfiguration').validator().on('submit', function(event) { }); } } else { + var initialHtml = $('.button-appStore-request').html(); $('.button-appStore-request').html('Please wait '); $('.button-appStore-request').prop('disabled', true); - publishApp('appStore'); + + publishApp('appStore').catch(function () { + $('.button-appStore-request').html(initialHtml); + $('.button-appStore-request').prop('disabled', false); + });; } // Gives time to Validator to apply classes @@ -2307,9 +2316,14 @@ $('#enterpriseConfiguration').validator().on('submit', function(event) { }); } } else { + var initialHtml = $('.button-enterprise-request').html(); $('.button-enterprise-request').html('Please wait '); $('.button-enterprise-request').prop('disabled', true); - publishApp('enterprise'); + + publishApp('enterprise').catch(function () { + $('.button-enterprise-request').html(initialHtml); + $('.button-enterprise-request').prop('disabled', false); + }); } // Gives time to Validator to apply classes @@ -2351,9 +2365,14 @@ $('#unsignedConfiguration').validator().on('submit', function(event) { }); } } else { + var initialHtml = $('.button-unsigned-request').html(); $('.button-unsigned-request').html('Please wait '); $('.button-unsigned-request').prop('disabled', true); - publishApp('unsigned'); + + publishApp('unsigned').catch(function () { + $('.button-unsigned-request').html(initialHtml); + $('.button-unsigned-request').prop('disabled', false); + }); } // Gives time to Validator to apply classes From 81920371a4889ca42714a9fdbc7f7ed0efe21a62 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Thu, 21 Feb 2019 11:21:55 +0000 Subject: [PATCH 113/318] Changes modal size to be smaller and more appropriate --- js/interface.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/js/interface.js b/js/interface.js index 7dbfd52..63de312 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1983,6 +1983,7 @@ function select2FADevice(data) { return Fliplet.Modal.prompt({ title: 'Your Apple ID is protected with two-step verification. Choose a trusted device to receive a verification code.', + size: 'small', inputType: 'select', inputOptions: options }).then(function (selection) { @@ -1992,7 +1993,8 @@ function select2FADevice(data) { if (selection === '') { return Fliplet.Modal.alert({ - message: 'You must choose a device to continue.' + message: 'You must choose a device to continue.', + size: 'small' }).then(function () { return select2FADevice(data); }); @@ -2004,7 +2006,8 @@ function select2FADevice(data) { function prompt2FA() { return Fliplet.Modal.prompt({ - title: 'A message with a verification code has been sent to your devices. Please enter the code to continue.

    If you are not certain which devices to check, please contact your Apple account administrator or IT team.' + title: 'A message with a verification code has been sent to your devices. Please enter the code to continue.
    Note: If you are not certain which devices to check, please contact your Apple account administrator or IT team.
    ', + size: 'small' }).then(function (code) { if (code === null) { return null; @@ -2012,7 +2015,8 @@ function prompt2FA() { if (code === '') { return Fliplet.Modal.alert({ - message: 'You must enter the verification code to continue.' + message: 'You must enter the verification code to continue.', + size: 'small' }).then(function () { return prompt2FA(); }); From 6626bba23350287c0d8f47951dc0a7c3a3ce3d57 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Thu, 21 Feb 2019 11:33:54 +0000 Subject: [PATCH 114/318] Ensures data parameter is available --- js/interface.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/interface.js b/js/interface.js index 63de312..5c77312 100644 --- a/js/interface.js +++ b/js/interface.js @@ -2905,7 +2905,7 @@ $('[name="submissionType"][value="appStore"]').prop('checked', true).trigger('ch initLoad = initialLoad(true, 0); // Listen for 2FA code when requested -socket.on('aab.apple.login.2fa', function () { +socket.on('aab.apple.login.2fa', function (data) { // Ask user for code prompt2FA().then(function (code) { if (code === null) { From e92c602250918117703b33fc483071d2108b5399 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Thu, 21 Feb 2019 18:54:28 +0000 Subject: [PATCH 115/318] 2FA message tweak --- js/interface.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/interface.js b/js/interface.js index 5c77312..95fee3b 100644 --- a/js/interface.js +++ b/js/interface.js @@ -2006,7 +2006,7 @@ function select2FADevice(data) { function prompt2FA() { return Fliplet.Modal.prompt({ - title: 'A message with a verification code has been sent to your devices. Please enter the code to continue.
    Note: If you are not certain which devices to check, please contact your Apple account administrator or IT team.
    ', + title: 'Apple has sent a verification code to your devices. Please enter the code to continue.
    Note: If you don\'t receive the code, please check your Apple account settings.
    ', size: 'small' }).then(function (code) { if (code === null) { From bbc01506168d77e416de6a25d4952ea1bcdbbf76 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Fri, 22 Feb 2019 12:27:22 +0000 Subject: [PATCH 116/318] Cleanup Avoids passing global organizationID variable unnecessarily --- js/interface.js | 213 +++++++++++++++++++++++++----------------------- 1 file changed, 113 insertions(+), 100 deletions(-) diff --git a/js/interface.js b/js/interface.js index 95fee3b..af5de81 100644 --- a/js/interface.js +++ b/js/interface.js @@ -237,53 +237,59 @@ function loadAppStoreData() { } } - //try to automaticaly login + // Try to automatically login if (appStoreSubmission.data && appStoreSubmission.data['fl-credentials']) { + // Submission data contains credential key var $loginButton = $('.login-appStore-button'); - $loginButton.html('Logging in'); + $loginButton.html('Logging in...'); $loginButton.addClass('disabled'); $('#fl-store-appDevPass').addClass('disabled'); $('#fl-store-appDevLogin').addClass('disabled'); - getCredential(organizationID, appStoreSubmission.data['fl-credentials']).then(function (credential) { - if (!credential.email || credential.email === null || typeof credential.email === 'undefined') { + + getCredential(appStoreSubmission.data['fl-credentials']) + .then(function (credential) { + if (!credential || !credential.email) { + // Allow users to manually log in if no email is found in credential + $loginButton.html('Log in'); + $('#fl-store-appDevLogin').removeClass('disabled'); + $('#fl-store-appDevPass').removeClass('disabled'); + $loginButton.removeClass('disabled'); + Fliplet.Widget.autosize(); + return; + } + + return appStoreTeamSetup(credential.email, $loginButton); + }) + .catch(function (error) { + // Allow users to manually log in if an error is encountered $loginButton.html('Log in'); $('#fl-store-appDevLogin').removeClass('disabled'); $('#fl-store-appDevPass').removeClass('disabled'); $loginButton.removeClass('disabled'); Fliplet.Widget.autosize(); - return; - } - return appStoreTeamSetup(credential.email, $loginButton); - }).catch(function (error) { - //we don't need to handle errors for automatic login - $loginButton.html('Log in'); - $('#fl-store-appDevLogin').removeClass('disabled'); - $('#fl-store-appDevPass').removeClass('disabled'); - $loginButton.removeClass('disabled'); - Fliplet.Widget.autosize(); - }); + console.error('Error retrieving previous app store submission credentials', error); + }); } } function appStoreTeamSetup(devEmail, loginButton) { - return getTeams(organizationID, appStoreSubmission.id, true) - .then(function(itunesTeams) { - var allPromises = []; - var portalTeamsPromise = getTeams(organizationID, appStoreSubmission.id, false); - allPromises.push(portalTeamsPromise); - allPromises.push(Promise.resolve(itunesTeams)); - - return Promise.all(allPromises); - }) - .then(function(teams) { - var appStoreTeams = _.filter(teams[0], function(team) { - var itunesTeam = _.find(teams[1], function(itcTeam) { + return Promise.all([ + getTeams(appStoreSubmission.id, false), + getTeams(appStoreSubmission.id, true) + ]) + .then(function (teams) { + var appStoreTeams = teams[0]; + var itunesTeams = teams[1]; + + appStoreTeams = _.filter(appStoreTeams, function(team) { + var itunesTeam = _.find(itunesTeams, function(itcTeam) { return itcTeam.team_name === team.name; }); return team.type === "Company/Organization" && !_.isUndefined(itunesTeam); }); + var options = ['']; appStoreTeams.forEach(function(team, i) { options.push(''); @@ -381,15 +387,17 @@ function loadEnterpriseData() { } } - //try to automaticaly login + // Try to automatically login if (enterpriseSubmission.data && enterpriseSubmission.data['fl-credentials']) { + // Submission data contains credential key var $loginButton = $('.login-enterprise-button'); - $loginButton.html('Logging in'); + $loginButton.html('Logging in...'); $loginButton.addClass('disabled'); $('#fl-ent-appDevLogin').addClass('disabled'); $('#fl-ent-appDevPass').addClass('disabled'); - getCredential(organizationID, enterpriseSubmission.data['fl-credentials']).then(function (credential) { - if (!credential.email || credential.email === null || typeof credential.email === 'undefined') { + + getCredential(enterpriseSubmission.data['fl-credentials']).then(function (credential) { + if (!credential || !credential.email) { $loginButton.html('Log in'); $('#fl-ent-appDevLogin').removeClass('disabled'); $('#fl-ent-appDevPass').removeClass('disabled'); @@ -400,18 +408,20 @@ function loadEnterpriseData() { return enterpriseTeamSetup(credential.email, $loginButton); }).catch(function (error) { - //we don't need to handle errors for automatic login + // Allow users to manually log in if an error is encountered $loginButton.html('Log in'); + $('#fl-store-appDevLogin').removeClass('disabled'); + $('#fl-store-appDevPass').removeClass('disabled'); $loginButton.removeClass('disabled'); - $('#fl-ent-appDevLogin').removeClass('disabled'); - $('#fl-ent-appDevPass').removeClass('disabled'); Fliplet.Widget.autosize(); + + console.error('Error retrieving previous enterprise submission credentials', error); }); } } function enterpriseTeamSetup(devEmail, loginButton) { - return getTeams(organizationID, enterpriseSubmission.id, false) + return getTeams(enterpriseSubmission.id, false) .then(function(teams) { var enterpriseTeams = _.filter(teams, function(team) { return team.type === "In-House"; @@ -604,12 +614,12 @@ function save(origin, submission) { if (origin === "appStore") { newSubmission.data['fl-credentials'] = 'submission-' + newSubmission.id; appStoreSubmission = newSubmission; - cloneCredentialsPromise = cloneCredentials(organizationID, previousCredentials, appStoreSubmission); + cloneCredentialsPromise = cloneCredentials(previousCredentials, appStoreSubmission); } if (origin === "enterprise") { newSubmission.data['fl-credentials'] = 'submission-' + newSubmission.id; enterpriseSubmission = newSubmission; - cloneCredentialsPromise = cloneCredentials(organizationID, previousCredentials, enterpriseSubmission); + cloneCredentialsPromise = cloneCredentials(previousCredentials, enterpriseSubmission); } if (origin === "unsigned") { unsignedSubmission = newSubmission; @@ -690,7 +700,7 @@ function requestBuild(origin, submission) { // Check which type of certificate was given if (origin === "appStore" && appStoreSubmission.data['fl-store-distribution'] === 'previous-file' && appStorePreviousCredential) { - return setCredentials(organizationID, appStoreSubmission.id, { + return setCredentials(appStoreSubmission.id, { teamId: appStorePreviousCredential.teamId, teamName: appStorePreviousCredential.teamName, certSigningRequest: appStorePreviousCredential.certSigningRequest, @@ -714,9 +724,9 @@ function requestBuild(origin, submission) { formData.append('certificateName', fileName) } - return setCertificateP12(organizationID, appStoreSubmission.id, formData) + return setCertificateP12(appStoreSubmission.id, formData) .then(function() { - return setCredentials(organizationID, appStoreSubmission.id, { + return setCredentials(appStoreSubmission.id, { teamId: teamID, teamName: teamName }); @@ -727,7 +737,7 @@ function requestBuild(origin, submission) { } if (origin === "enterprise" && enterpriseSubmission.data['fl-ent-distribution'] === 'previous-file' && enterprisePreviousCredential) { - return setCredentials(organizationID, enterpriseSubmission.id, { + return setCredentials(enterpriseSubmission.id, { teamId: enterprisePreviousCredential.teamId, teamName: enterprisePreviousCredential.teamName, certSigningRequest: enterprisePreviousCredential.certSigningRequest, @@ -752,15 +762,15 @@ function requestBuild(origin, submission) { var teamId = $('#fl-ent-teams').val(); var teamName = $('#fl-ent-teams').find(":selected").data('team-name'); - return setCredentials(organizationID, enterpriseSubmission.id, { + return setCredentials(enterpriseSubmission.id, { teamId: teamId, teamName: teamName }) .then(function() { - return setCertificateP12(organizationID, enterpriseSubmission.id, formData) + return setCertificateP12(enterpriseSubmission.id, formData) }) .then(function() { - return setCredentials(organizationID, enterpriseSubmission.id, { + return setCredentials(enterpriseSubmission.id, { teamId: teamID, teamName: teamName }); @@ -777,7 +787,7 @@ function requestBuild(origin, submission) { Fliplet.App.Submissions.update(submission.id, submission.data).then(function() { // Check which type of certificate was given if (origin === "appStore" && appStoreSubmission.data['fl-store-distribution'] === 'previous-file' && appStorePreviousCredential) { - return setCredentials(organizationID, appStoreSubmission.id, { + return setCredentials(appStoreSubmission.id, { teamId: appStorePreviousCredential.teamId, teamName: appStorePreviousCredential.teamName, certSigningRequest: appStorePreviousCredential.certSigningRequest, @@ -801,9 +811,9 @@ function requestBuild(origin, submission) { formData.append('certificateName', fileName) } - return setCertificateP12(organizationID, appStoreSubmission.id, formData) + return setCertificateP12(appStoreSubmission.id, formData) .then(function() { - return setCredentials(organizationID, appStoreSubmission.id, { + return setCredentials(appStoreSubmission.id, { teamId: teamID, teamName: teamName }); @@ -814,7 +824,7 @@ function requestBuild(origin, submission) { } if (origin === "enterprise" && enterpriseSubmission.data['fl-ent-distribution'] === 'previous-file' && enterprisePreviousCredential) { - return setCredentials(organizationID, enterpriseSubmission.id, { + return setCredentials(enterpriseSubmission.id, { teamId: enterprisePreviousCredential.teamId, teamName: enterprisePreviousCredential.teamName, certSigningRequest: enterprisePreviousCredential.certSigningRequest, @@ -838,9 +848,9 @@ function requestBuild(origin, submission) { formData.append('certificateName', fileName) } - return setCertificateP12(organizationID, enterpriseSubmission.id, formData) + return setCertificateP12(enterpriseSubmission.id, formData) .then(function() { - return setCredentials(organizationID, enterpriseSubmission.id, { + return setCredentials(enterpriseSubmission.id, { teamId: teamID, teamName: teamName }); @@ -1103,10 +1113,10 @@ function savePushData(silentSave) { }); } -function cloneCredentials(organizationId, credentialKey, submission, saveData) { +function cloneCredentials(credentialKey, submission, saveData) { return Fliplet.API.request({ method: 'POST', - url: 'v1/organizations/' + organizationId + '/credentials/' + credentialKey + '/clone', + url: 'v1/organizations/' + organizationID + '/credentials/' + credentialKey + '/clone', data: { key: submission.data['fl-credentials'] } @@ -1116,35 +1126,33 @@ function cloneCredentials(organizationId, credentialKey, submission, saveData) { } return Promise.resolve(); - }).catch(function() { - //do nothing, a new credential will be created after the user logs in }); } -function setCredentials(organizationId, id, data, verify) { +function setCredentials(id, data, verify) { verify = typeof verify === 'undefined' ? true : verify; return Fliplet.API.request({ method: 'PUT', - url: 'v1/organizations/' + organizationId + '/credentials/submission-' + id + '?verify=' + verify, + url: 'v1/organizations/' + organizationID + '/credentials/submission-' + id + '?verify=' + verify, data: data }); } -function getTeams(organizationId, id, isItunes) { +function getTeams(id, isItunes) { return Fliplet.API.request({ method: 'GET', - url: 'v1/organizations/' + organizationId + '/credentials/submission-' + id + '/teams?itunes=' + isItunes + url: 'v1/organizations/' + organizationID + '/credentials/submission-' + id + '/teams?itunes=' + isItunes }) .then(function(result) { return Promise.resolve(result.teams); }); } -function searchCredentials(organizationId, data) { +function searchCredentials(data) { return Fliplet.API.request({ method: 'POST', - url: 'v1/organizations/' + organizationId + '/credentials/search', + url: 'v1/organizations/' + organizationID + '/credentials/search', data: data }) .then(function(credentials) { @@ -1152,9 +1160,9 @@ function searchCredentials(organizationId, data) { }); } -function getAppCredentials(organizationId, credentialKey, teamId) { +function getAppCredentials(credentialKey, teamId) { if(credentialKey) { - return getCredential(organizationId, credentialKey) + return getCredential(credentialKey) .then(function(credential) { if(credential && credential.teamId === teamId && (credential.p12 || credential.certificate)) { return credential; @@ -1186,15 +1194,14 @@ function refreshAppStoreOptions(devEmail, selectedTeamId, selectedTeamName) { return; } - return getAppCredentials(organizationID, - appStoreSubmission.data['fl-credentials'], + return getAppCredentials(appStoreSubmission.data['fl-credentials'], selectedTeamId) .then(function(credential) { if(credential) { return credential; } - return searchCredentials(organizationID, { + return searchCredentials({ email: devEmail, type: 'apple', teamId: selectedTeamId @@ -1212,7 +1219,7 @@ function refreshAppStoreOptions(devEmail, selectedTeamId, selectedTeamName) { } if(credentialKey) { - return getCredential(organizationID, credentialKey); + return getCredential(credentialKey); } return; @@ -1225,6 +1232,7 @@ function refreshAppStoreOptions(devEmail, selectedTeamId, selectedTeamName) { if(credential) { return credential; } + var previousResults = appStoreSubmission.data.previousResults; //make sure that previous results are obtained from latest completed submission. if (!_.isUndefined(previousAppStoreSubmission)) { @@ -1243,7 +1251,7 @@ function refreshAppStoreOptions(devEmail, selectedTeamId, selectedTeamName) { }; } - return getCompletedSubmissions(organizationID, devEmail, selectedTeamId, selectedTeamName); + return getCompletedSubmissions(devEmail, selectedTeamId, selectedTeamName); }) .then(function(credential) { return setAppStorePrevCredentials(credential); @@ -1272,15 +1280,14 @@ function refreshAppEnterpriseOptions(devEmail, selectedTeamId, selectedTeamName) return; } - return getAppCredentials(organizationID, - enterpriseSubmission.data['fl-credentials'], + return getAppCredentials(enterpriseSubmission.data['fl-credentials'], selectedTeamId) .then(function(credential) { if(credential) { return credential; } - return searchCredentials(organizationID, { + return searchCredentials({ email: devEmail, type: 'apple-enterprise', teamId: selectedTeamId @@ -1298,7 +1305,7 @@ function refreshAppEnterpriseOptions(devEmail, selectedTeamId, selectedTeamName) } if(credentialKey) { - return getCredential(organizationID, credentialKey); + return getCredential(credentialKey); } return; @@ -1311,11 +1318,13 @@ function refreshAppEnterpriseOptions(devEmail, selectedTeamId, selectedTeamName) if(credential) { return credential; } + var previousResults = enterpriseSubmission.data.previousResults; //make sure that previous results are obtained from latest completed submission. if (!_.isUndefined(previousEnterpriseStoreSubmission)) { previousResults = previousEnterpriseStoreSubmission.result; } + //if we dont have any credentials we need to check previous result for a credential object if(!_.isUndefined(previousResults) && (!_.isUndefined(previousResults.p12) || !_.isUndefined(previousResults.certificate)) && enterpriseSubmission.data['fl-ent-teamId'] === selectedTeamId) { return { @@ -1328,7 +1337,7 @@ function refreshAppEnterpriseOptions(devEmail, selectedTeamId, selectedTeamName) }; } - return getCompletedSubmissions(organizationID, devEmail, selectedTeamId, selectedTeamName); + return getCompletedSubmissions(devEmail, selectedTeamId, selectedTeamName); }) .then(function(credential) { return setAppEnterprisePrevCredential(credential); @@ -1338,7 +1347,7 @@ function refreshAppEnterpriseOptions(devEmail, selectedTeamId, selectedTeamName) }); } -function getCompletedSubmissions(organizationId, devEmail, teamId, teamName) { +function getCompletedSubmissions(devEmail, teamId, teamName) { var statusList = [ 'started', // Default status when the submission is started from the user 'submitted', // Submission has been submitted @@ -1354,7 +1363,7 @@ function getCompletedSubmissions(organizationId, devEmail, teamId, teamName) { return s !== 'failed'; }); var url = [ - 'v1/organizations/' + organizationId, + 'v1/organizations/' + organizationID, '/submissions?status=' + statusFilter.join(','), '&email=' + devEmail, '&teamId=' + teamId @@ -1391,13 +1400,24 @@ function getCompletedSubmissions(organizationId, devEmail, teamId, teamName) { }); } -function getCredential(organizationId, credentialKey) { +function getCredential(credentialKey) { return Fliplet.API.request({ method: 'GET', - url: 'v1/organizations/' + organizationId + '/credentials/' + credentialKey + url: 'v1/organizations/' + organizationID + '/credentials/' + credentialKey }) .then(function(credential) { + if (!credential || !credential.email) { + return Promise.resolve(); + } + return Promise.resolve(credential); + }) + .catch(function (error) { + if (error && error.status === 404) { + return Promise.resolve(); + } + + return Promise.reject(error); }); } @@ -1415,30 +1435,23 @@ function createCertificates(options) { }); } -function setCertificateP12(organizationId, id, file) { +function setCertificateP12(id, file) { return Fliplet.API.request({ method: 'PUT', - url: 'v1/organizations/' + organizationId + '/credentials/submission-' + id + '?fileName=p12', + url: 'v1/organizations/' + organizationID + '/credentials/submission-' + id + '?fileName=p12', data: file, contentType: false, processData: false - }) - .then(function() { - return Promise.resolve(); }); } -function revokeCertificate(organizationId, id, certId) { +function revokeCertificate(id, certId) { return Fliplet.API.request({ method: 'DELETE', - url: 'v1/organizations/' + organizationId + '/credentials/submission-' + id + '/' + certId - }) - .then(function(result) { - return Promise.resolve(); + url: 'v1/organizations/' + organizationID + '/credentials/submission-' + id + '/' + certId }); } - function init() { Fliplet.Apps.get().then(function(apps) { appInfo = _.find(apps, function(app) { @@ -1696,7 +1709,7 @@ function submissionChecker(submissions) { appStoreSubmission.data['fl-credentials'] = 'submission-' + appStoreSubmission.id; if(previousSubWithCredentials) { - cloneAppStoreCredentialsPromise = cloneCredentials(organizationID, previousSubWithCredentials.data['fl-credentials'], appStoreSubmission, true); + cloneAppStoreCredentialsPromise = cloneCredentials(previousSubWithCredentials.data['fl-credentials'], appStoreSubmission, true); } } @@ -1739,7 +1752,7 @@ function submissionChecker(submissions) { enterpriseSubmission.data['fl-credentials'] = 'submission-' + enterpriseSubmission.id; if(previousSubWithCredentials) { - cloneEnterpriseCredentialsPromise = cloneCredentials(organizationID, previousSubWithCredentials.data['fl-credentials'], enterpriseSubmission, true); + cloneEnterpriseCredentialsPromise = cloneCredentials(previousSubWithCredentials.data['fl-credentials'], enterpriseSubmission, true); } } @@ -1910,7 +1923,7 @@ function initialLoad(initial, timeout) { }), Fliplet.API.request({ method: 'GET', - url: 'v1/organizations/' + Fliplet.Env.get('organizationId') + url: 'v1/organizations/' + organizationID }) .then(function(org) { organizationName = org.name; @@ -2430,7 +2443,7 @@ $('.login-appStore-button').on('click', function() { } if (devEmail !== '' && devPass !== '') { - setCredentials(organizationID, appStoreSubmission.id, { + setCredentials(appStoreSubmission.id, { type: 'apple', status: 'created', email: devEmail, @@ -2450,7 +2463,7 @@ $('.login-appStore-button').on('click', function() { }); $('.log-out-appStore').on('click', function() { - setCredentials(organizationID, appStoreSubmission.id, { + setCredentials(appStoreSubmission.id, { email: null, password: null, teamId: null @@ -2522,7 +2535,7 @@ $('.appStore-generate-cert').on('click', function() { appStoreTeamId = teamId; var teamName = $('#fl-store-teams').find(":selected").data('team-name'); - return setCredentials(organizationID, appStoreSubmission.id, { + return setCredentials(appStoreSubmission.id, { teamId: teamId, teamName: teamName }) @@ -2570,9 +2583,9 @@ $('.appStore-replace-cert').on('click', function() { var teamName = appStorePreviousCredential ? appStorePreviousCredential.teamName : ''; if (appStorePreviousCredential.certificate && appStorePreviousCredential.certificate.id) { - return revokeCertificate(organizationID, appStoreSubmission.id, appStorePreviousCredential.certificate.id) + return revokeCertificate(appStoreSubmission.id, appStorePreviousCredential.certificate.id) .then(function() { - return setCredentials(organizationID, appStoreSubmission.id, { + return setCredentials(appStoreSubmission.id, { teamId: teamId, teamName: teamName }) @@ -2641,7 +2654,7 @@ $('.login-enterprise-button').on('click', function() { } if (devEmail !== '' && devPass !== '') { - setCredentials(organizationID, enterpriseSubmission.id, { + setCredentials(enterpriseSubmission.id, { type: 'apple-enterprise', status: 'created', email: devEmail, @@ -2662,7 +2675,7 @@ $('.login-enterprise-button').on('click', function() { }); $('.log-out-enterprise').on('click', function() { - setCredentials(organizationID, enterpriseSubmission.id, { + setCredentials(enterpriseSubmission.id, { email: null, password: null, teamId: null @@ -2731,7 +2744,7 @@ $('.enterprise-generate-cert').on('click', function() { enterpriseTeamId = teamId; var teamName = $('#fl-ent-teams').find(":selected").data('team-name'); - return setCredentials(organizationID, enterpriseSubmission.id, { + return setCredentials(enterpriseSubmission.id, { teamId: teamId, teamName: teamName }) @@ -2798,9 +2811,9 @@ $('.enterprise-replace-cert').on('click', function() { var teamName = enterprisePreviousCredential ? enterprisePreviousCredential.teamName : ''; if (enterprisePreviousCredential.certificate && enterprisePreviousCredential.certificate.id) { - return revokeCertificate(organizationID, enterpriseSubmission.id, enterprisePreviousCredential.certificate.id) + return revokeCertificate(enterpriseSubmission.id, enterprisePreviousCredential.certificate.id) .then(function() { - return setCredentials(organizationID, enterpriseSubmission.id, { + return setCredentials(enterpriseSubmission.id, { teamId: teamId, teamName: teamName }) From 03fdbc9b82ff31546abe083c8de568efcb7f1860 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Fri, 22 Feb 2019 12:33:00 +0000 Subject: [PATCH 117/318] Adds comments --- js/interface.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/interface.js b/js/interface.js index af5de81..db4c525 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1407,6 +1407,7 @@ function getCredential(credentialKey) { }) .then(function(credential) { if (!credential || !credential.email) { + // Valid credential email not found return Promise.resolve(); } @@ -1414,6 +1415,7 @@ function getCredential(credentialKey) { }) .catch(function (error) { if (error && error.status === 404) { + // Credential not found return Promise.resolve(); } From 86f8962a36826df39c810f277289510949e7105d Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Fri, 22 Feb 2019 14:50:48 +0000 Subject: [PATCH 118/318] Makes team loading a manual step --- css/interface.css | 4 +- interface.html | 32 +++--- js/interface.js | 267 +++++++++++++++++++++++++++++++++------------- 3 files changed, 210 insertions(+), 93 deletions(-) diff --git a/css/interface.css b/css/interface.css index cf1c8a8..64f058d 100644 --- a/css/interface.css +++ b/css/interface.css @@ -22,7 +22,9 @@ .enterprise-previous-file-success, .enterprise-generate-file, .enterprise-generate-file-success, -.enterprise-upload-file { +.enterprise-upload-file, +.select-proxy-display[for="fl-store-teams"], +.select-proxy-display[for="fl-ent-teams"] { display: none; } diff --git a/interface.html b/interface.html index 7dea706..9be287f 100644 --- a/interface.html +++ b/interface.html @@ -551,9 +551,6 @@

    Apple developer account details and distribution certificates

    If you do not know what the developer account login details are please contact your organization's IT team.

    -
    -

    Note If your account has Two-Factor Authentication enabled and you can't turn it off, please ask IT to create a secondary account without 2FA to be used with Fliplet.

    -
    @@ -602,12 +599,13 @@

    Apple developer account details and distribution certificates

    - + +
    @@ -1146,9 +1144,6 @@

    Apple developer account details and distribution certificates

    If you don't know what the developer account login details are please contact your organization's IT team.

    -
    -

    Note Two-Factor Authentication is not currently supported.

    -
    @@ -1259,12 +1254,13 @@

    Apple developer account details and distribution certificates

    - + +
    diff --git a/js/interface.js b/js/interface.js index db4c525..5da136f 100644 --- a/js/interface.js +++ b/js/interface.js @@ -40,6 +40,7 @@ var screenShotsMobile = []; var screenShotsTablet = []; var haveScreenshots = false; var screenshotValidationNotRequired = false; +var spinner = ''; var socket = Fliplet.Socket({ transports: ['polling'], // avoid being blocked by AdBlockers @@ -241,7 +242,7 @@ function loadAppStoreData() { if (appStoreSubmission.data && appStoreSubmission.data['fl-credentials']) { // Submission data contains credential key var $loginButton = $('.login-appStore-button'); - $loginButton.html('Logging in...'); + $loginButton.html('Logging in' + spinner); $loginButton.addClass('disabled'); $('#fl-store-appDevPass').addClass('disabled'); $('#fl-store-appDevLogin').addClass('disabled'); @@ -258,7 +259,9 @@ function loadAppStoreData() { return; } - return appStoreTeamSetup(credential.email, $loginButton); + $loginButton.html('Log in'); + $loginButton.removeClass('disabled'); + return appStoreTeamSetup(credential.email); }) .catch(function (error) { // Allow users to manually log in if an error is encountered @@ -267,20 +270,36 @@ function loadAppStoreData() { $('#fl-store-appDevPass').removeClass('disabled'); $loginButton.removeClass('disabled'); Fliplet.Widget.autosize(); - - console.error('Error retrieving previous app store submission credentials', error); }); } } -function appStoreTeamSetup(devEmail, loginButton) { - return Promise.all([ - getTeams(appStoreSubmission.id, false), - getTeams(appStoreSubmission.id, true) - ]) +function clearAppStoreCredentials() { + return setCredentials(appStoreSubmission.id, { + email: null, + password: null, + teamId: null + }, false).then(function () { + appStoreLoggedIn = false; + $('#fl-store-appDevPass').prop('required', true); + $('.appStore-logged-email').html(''); + $('.appStore-login-details').removeClass('hidden'); + $('.appStore-logged-in, .appStore-more-options, .appStore-teams').removeClass('show'); + }); +} + +function loadAppStoreTeams(devEmail) { + // We're avoiding making both calls in one go with Promise.all() to avoid 2FA requests being received twice + return getTeams(appStoreSubmission.id, true) + .then(function (itunesTeams) { + return Promise.all([ + Promise.resolve(itunesTeams), + getTeams(appStoreSubmission.id, false) + ]); + }) .then(function (teams) { - var appStoreTeams = teams[0]; - var itunesTeams = teams[1]; + var itunesTeams = teams[0]; + var appStoreTeams = teams[1]; appStoreTeams = _.filter(appStoreTeams, function(team) { var itunesTeam = _.find(itunesTeams, function(itcTeam) { @@ -292,19 +311,11 @@ function appStoreTeamSetup(devEmail, loginButton) { var options = ['']; appStoreTeams.forEach(function(team, i) { - options.push(''); + options.push(''); }); - $('#fl-store-teams').html(options.join('')); + $('#fl-load-store-teams').hide(); + $('#fl-store-teams').html(options.join('')).parent().show(); - $('#fl-store-appDevLogin').removeClass('disabled'); - $('#fl-store-appDevPass').removeClass('disabled'); - $('#fl-store-appDevLogin').val(devEmail); - $('#fl-store-appDevPass').prop('required', false); - loginButton.html('Log in'); - loginButton.removeClass('disabled'); - $('.appStore-logged-email').html(devEmail); - $('.appStore-login-details').addClass('hidden'); - $('.appStore-logged-in, .appStore-teams').addClass('show'); appStoreLoggedIn = true; var teamId = $('#fl-store-teams').val(); var teamName = teamId ? $('#fl-store-teams').find(":selected").data('team-name') : ''; @@ -319,6 +330,24 @@ function appStoreTeamSetup(devEmail, loginButton) { }); } +function appStoreTeamSetup(devEmail, loadTeams) { + var load = Promise.resolve(); + + if (loadTeams) { + load = loadAppStoreTeams(devEmail); + } + + return load.then(function () { + $('#fl-store-appDevLogin').removeClass('disabled'); + $('#fl-store-appDevPass').removeClass('disabled'); + $('#fl-store-appDevLogin').val(devEmail); + $('#fl-store-appDevPass').prop('required', false); + $('.appStore-logged-email').html(devEmail); + $('.appStore-login-details').addClass('hidden'); + $('.appStore-logged-in, .appStore-teams').addClass('show'); + }); +} + function loadEnterpriseData() { $('#enterpriseConfiguration [name]').each(function(i, el) { var name = $(el).attr("name"); @@ -391,7 +420,7 @@ function loadEnterpriseData() { if (enterpriseSubmission.data && enterpriseSubmission.data['fl-credentials']) { // Submission data contains credential key var $loginButton = $('.login-enterprise-button'); - $loginButton.html('Logging in...'); + $loginButton.html('Logging in' + spinner); $loginButton.addClass('disabled'); $('#fl-ent-appDevLogin').addClass('disabled'); $('#fl-ent-appDevPass').addClass('disabled'); @@ -406,7 +435,9 @@ function loadEnterpriseData() { return; } - return enterpriseTeamSetup(credential.email, $loginButton); + $loginButton.html('Log in'); + $loginButton.removeClass('disabled'); + return enterpriseTeamSetup(credential.email); }).catch(function (error) { // Allow users to manually log in if an error is encountered $loginButton.html('Log in'); @@ -420,7 +451,21 @@ function loadEnterpriseData() { } } -function enterpriseTeamSetup(devEmail, loginButton) { +function clearEnterpriseCredentials() { + return setCredentials(enterpriseSubmission.id, { + email: null, + password: null, + teamId: null + }, false).then(function () { + enterpriseLoggedIn = false; + $('#fl-ent-appDevPass').prop('required', true); + $('.enterprise-logged-email').html(''); + $('.enterprise-login-details').removeClass('hidden'); + $('.enterprise-logged-in, .enterprise-more-options, .enterprise-teams').removeClass('show'); + }); +} + +function loadEnterpriseTeams(devEmail) { return getTeams(enterpriseSubmission.id, false) .then(function(teams) { var enterpriseTeams = _.filter(teams, function(team) { @@ -430,17 +475,9 @@ function enterpriseTeamSetup(devEmail, loginButton) { enterpriseTeams.forEach(function(team, i) { options.push(''); }); - $('#fl-ent-teams').html(options.join('')); - - $('#fl-ent-appDevLogin').removeClass('disabled'); - $('#fl-ent-appDevPass').removeClass('disabled'); - $('#fl-ent-appDevLogin').val(devEmail); - $('#fl-ent-appDevPass').prop('required', false); - loginButton.html('Log in'); - loginButton.removeClass('disabled'); - $('.enterprise-logged-email').html(devEmail); - $('.enterprise-login-details').addClass('hidden'); - $('.enterprise-logged-in, .enterprise-more-options, .enterprise-teams').addClass('show'); + $('#fl-load-ent-teams').hide(); + $('#fl-ent-teams').html(options.join('')).parent().show(); + enterpriseLoggedIn = true; var teamId = $('#fl-ent-teams').val(); var teamName = teamId ? $('#fl-ent-teams').find(":selected").data('team-name') : ''; @@ -455,6 +492,24 @@ function enterpriseTeamSetup(devEmail, loginButton) { }); } +function enterpriseTeamSetup(devEmail, loadTeams) { + var load = Promise.resolve(); + + if (loadTeams) { + load = loadEnterpriseTeams(devEmail); + } + + return load.then(function () { + $('#fl-ent-appDevLogin').removeClass('disabled'); + $('#fl-ent-appDevPass').removeClass('disabled'); + $('#fl-ent-appDevLogin').val(devEmail); + $('#fl-ent-appDevPass').prop('required', false); + $('.enterprise-logged-email').html(devEmail); + $('.enterprise-login-details').addClass('hidden'); + $('.enterprise-logged-in, .enterprise-teams').addClass('show'); + }); +} + function loadUnsignedData() { $('#unsignedConfiguration [name]').each(function(i, el) { var name = $(el).attr("name"); @@ -653,7 +708,7 @@ function save(origin, submission) { } function requestBuild(origin, submission) { - $('.button-' + origin + '-request').html('Requesting '); + $('.button-' + origin + '-request').html('Requesting' + spinner); if (origin === 'appStore') { submission.data.folderStructure = appSettings.folderStructure; @@ -2255,7 +2310,7 @@ $('#appStoreConfiguration').validator().on('submit', function(event) { } } else { var initialHtml = $('.button-appStore-request').html(); - $('.button-appStore-request').html('Please wait '); + $('.button-appStore-request').html('Please wait' + spinner); $('.button-appStore-request').prop('disabled', true); publishApp('appStore').catch(function () { @@ -2335,7 +2390,7 @@ $('#enterpriseConfiguration').validator().on('submit', function(event) { } } else { var initialHtml = $('.button-enterprise-request').html(); - $('.button-enterprise-request').html('Please wait '); + $('.button-enterprise-request').html('Please wait' + spinner); $('.button-enterprise-request').prop('disabled', true); publishApp('enterprise').catch(function () { @@ -2384,7 +2439,7 @@ $('#unsignedConfiguration').validator().on('submit', function(event) { } } else { var initialHtml = $('.button-unsigned-request').html(); - $('.button-unsigned-request').html('Please wait '); + $('.button-unsigned-request').html('Please wait' + spinner); $('.button-unsigned-request').prop('disabled', true); publishApp('unsigned').catch(function () { @@ -2414,7 +2469,7 @@ $('[data-push-save]').on('click', function() { /* Credentials and Certificates App Store */ $('.login-appStore-button').on('click', function() { var $this = $(this); - $(this).html('Logging in...'); + $(this).html('Logging in' + spinner); $(this).addClass('disabled'); var devEmail = $('#fl-store-appDevLogin').val(); var devPass = $('#fl-store-appDevPass').val(); @@ -2452,11 +2507,24 @@ $('.login-appStore-button').on('click', function() { password: devPass }) .then(function() { - return appStoreTeamSetup(devEmail, $this); + $this.html('Log in'); + $this.removeClass('disabled'); + return appStoreTeamSetup(devEmail, true); }) .catch(function(error) { - console.log(error); - $this.nextAll('.login-error').html(Fliplet.parseError(error)); + var message = 'Unable to log in'; + + if (Fliplet.parseError(error)) { + message += '
    ' + Fliplet.parseError(error) + '
    ' + } + + Fliplet.Modal.alert({ + message: message, + size: 'small' + }); + + $('.appStore-login-details').removeClass('hidden'); + $('.appStore-logged-in, .appStore-teams').removeClass('show'); $this.html('Log in'); $this.removeClass('disabled'); Fliplet.Widget.autosize(); @@ -2465,17 +2533,7 @@ $('.login-appStore-button').on('click', function() { }); $('.log-out-appStore').on('click', function() { - setCredentials(appStoreSubmission.id, { - email: null, - password: null, - teamId: null - }, false).then(function () { - appStoreLoggedIn = false; - $('#fl-store-appDevPass').prop('required', true); - $('.appStore-logged-email').html(''); - $('.appStore-login-details').removeClass('hidden'); - $('.appStore-logged-in, .appStore-more-options, .appStore-teams').removeClass('show'); - }); + clearAppStoreCredentials(); }); $('[name="fl-store-distribution"]').on('change', function() { @@ -2510,6 +2568,35 @@ $('[name="fl-store-distribution"]').on('change', function() { Fliplet.Widget.autosize(); }); +$('#fl-load-store-teams').on('click', function (e) { + e.preventDefault(); + var $button = $(this); + var initialLabel = $button.html(); + $button.html('Loading' + spinner).addClass('disabled'); + loadAppStoreTeams($('.appStore-logged-email').text()) + .then(function () { + $button.html(initialLabel).removeClass('disabled'); + }) + .catch(function (error) { + $button.html(initialLabel).removeClass('disabled'); + + var message = 'Unable to load teams'; + + if (Fliplet.parseError(error)) { + message += '
    ' + Fliplet.parseError(error) + '
    ' + } + + Fliplet.Modal.alert({ + message: message, + size: 'small' + }); + + if (error && Fliplet.parseError(error).match(/^The email or password you entered .+ are wrong/)) { + clearAppStoreCredentials(); + } + }); +}); + $('#fl-store-teams').on('change', function() { var value = $(this).val(); var teamName = value ? $('#fl-store-teams').find(":selected").data('team-name') : ''; @@ -2530,7 +2617,7 @@ $('#fl-store-teams').on('change', function() { $('.appStore-generate-cert').on('click', function() { var $this = $(this); - $(this).html('Generating...'); + $(this).html('Generating' + spinner); $(this).addClass('disabled'); $('.generate-error').html(''); // Cleans errors var teamId = $('#fl-store-teams').val(); @@ -2577,7 +2664,7 @@ $('#fl-store-certificate').on('change', function() { $('.appStore-replace-cert').on('click', function() { var $this = $(this); - $(this).html('Replacing...'); + $(this).html('Replacing' + spinner); $(this).addClass('disabled'); $('.replace-error').html(''); // Cleans errors var teamId = appStorePreviousCredential ? appStorePreviousCredential.teamId : ''; @@ -2625,7 +2712,7 @@ $('.appStore-replace-cert').on('click', function() { /* Credentials and Certificates Enterprise */ $('.login-enterprise-button').on('click', function() { var $this = $(this); - $(this).html('Logging in...'); + $(this).html('Logging in' + spinner); $(this).addClass('disabled'); var devEmail = $('#fl-ent-appDevLogin').val(); var devPass = $('#fl-ent-appDevPass').val(); @@ -2664,11 +2751,24 @@ $('.login-enterprise-button').on('click', function() { }) .then(function() { $('[name="fl-ent-distribution"][value="generate-file"]').prop('checked', true).trigger('change'); - return enterpriseTeamSetup(devEmail, $this); + $this.html('Log in'); + $this.removeClass('disabled'); + return enterpriseTeamSetup(devEmail, true); }) .catch(function(error) { - console.log(error); - $this.nextAll('.login-error').html(Fliplet.parseError(error)); + var message = 'Unable to log in'; + + if (Fliplet.parseError(error)) { + message += '
    ' + Fliplet.parseError(error) + '
    ' + } + + Fliplet.Modal.alert({ + message: message, + size: 'small' + }); + + $('.enterprise-login-details').removeClass('hidden'); + $('.enterprise-logged-in, .enterprise-more-options, .enterprise-teams').removeClass('show'); $this.html('Log in'); $this.removeClass('disabled'); Fliplet.Widget.autosize(); @@ -2677,17 +2777,7 @@ $('.login-enterprise-button').on('click', function() { }); $('.log-out-enterprise').on('click', function() { - setCredentials(enterpriseSubmission.id, { - email: null, - password: null, - teamId: null - }, false).then(function () { - enterpriseLoggedIn = false; - $('#fl-ent-appDevPass').prop('required', true); - $('.enterprise-logged-email').html(''); - $('.enterprise-login-details').removeClass('hidden'); - $('.enterprise-logged-in, .enterprise-more-options, .enterprise-teams').removeClass('show'); - }); + clearEnterpriseCredentials(); }); $('[name="fl-ent-distribution"]').on('change', function() { @@ -2719,6 +2809,35 @@ $('[name="fl-ent-distribution"]').on('change', function() { Fliplet.Widget.autosize(); }); +$('#fl-load-ent-teams').on('click', function (e) { + e.preventDefault(); + var $button = $(this); + var initialLabel = $button.html(); + $button.html('Loading' + spinner).addClass('disabled'); + loadEnterpriseTeams($('.enterprise-logged-email').text()) + .then(function () { + $button.html(initialLabel).removeClass('disabled'); + }) + .catch(function (error) { + $button.html(initialLabel).removeClass('disabled'); + + var message = 'Unable to load teams'; + + if (Fliplet.parseError(error)) { + message += '
    ' + Fliplet.parseError(error) + '
    ' + } + + Fliplet.Modal.alert({ + message: message, + size: 'small' + }); + + if (error && Fliplet.parseError(error).match(/^The email or password you entered .+ are wrong/)) { + clearEnterpriseCredentials(); + } + }); +}); + $('#fl-ent-teams').on('change', function() { var value = $(this).val(); var teamName = value ? $('#fl-ent-teams').find(":selected").data('team-name') : ''; @@ -2739,7 +2858,7 @@ $('#fl-ent-teams').on('change', function() { $('.enterprise-generate-cert').on('click', function() { var $this = $(this); - $(this).html('Generating...'); + $(this).html('Generating' + spinner); $(this).addClass('disabled'); $('.generate-error').html(''); // Cleans errors var teamId = $('#fl-ent-teams').val(); @@ -2805,7 +2924,7 @@ $('#fl-ent-mobileprovision-manual-details').on('change', function() { $('.enterprise-replace-cert').on('click', function() { var $this = $(this); - $(this).html('Replacing...'); + $(this).html('Replacing' + spinner); $(this).addClass('disabled'); $('.replace-error').html(''); // Cleans errors var teamId = enterprisePreviousCredential ? enterprisePreviousCredential.teamId : ''; From 18afbacda3651d40661fa0a466e983a9cf920b63 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Fri, 22 Feb 2019 14:51:34 +0000 Subject: [PATCH 119/318] Spaces --- js/interface.js | 188 ++++++++++++++++++++++++------------------------ 1 file changed, 94 insertions(+), 94 deletions(-) diff --git a/js/interface.js b/js/interface.js index 5da136f..48f305c 100644 --- a/js/interface.js +++ b/js/interface.js @@ -48,7 +48,7 @@ var socket = Fliplet.Socket({ }); /* FUNCTIONS */ -String.prototype.toCamelCase = function() { +String.prototype.toCamelCase = function () { return this.replace(/^([A-Z])|[^A-Za-z]+(\w)/g, function(match, p1, p2, offset) { if (p2) return p2.toUpperCase(); return p1.toLowerCase(); @@ -320,7 +320,7 @@ function loadAppStoreTeams(devEmail) { var teamId = $('#fl-store-teams').val(); var teamName = teamId ? $('#fl-store-teams').find(":selected").data('team-name') : ''; - if(teamId) { + if (teamId) { $('.appStore-more-options').addClass('show'); } else { $('.appStore-more-options').removeClass('show'); @@ -482,7 +482,7 @@ function loadEnterpriseTeams(devEmail) { var teamId = $('#fl-ent-teams').val(); var teamName = teamId ? $('#fl-ent-teams').find(":selected").data('team-name') : ''; - if(teamId) { + if (teamId) { $('.enterprise-more-options').addClass('show'); } else { $('.enterprise-more-options').removeClass('show'); @@ -625,8 +625,8 @@ function submissionBuild(appSubmission, origin) { Fliplet.Widget.autosize(); - setTimeout(function() { - $('.save-' + origin + '-request').fadeOut(250, function() { + setTimeout(function () { + $('.save-' + origin + '-request').fadeOut(250, function () { $('.save-' + origin + '-request').removeClass('saved'); Fliplet.Widget.autosize(); }); @@ -651,10 +651,10 @@ function save(origin, submission) { submission = _.extend(savedSubmission, submission); return Promise.resolve(); }) - .then(function() { + .then(function () { if (submission.status !== 'started') { var previousCredentials = submission.data['fl-credentials']; - if(submission.data.hasOwnProperty('fl-credentials')){ + if (submission.data.hasOwnProperty('fl-credentials')) { delete submission.data['fl-credentials']; } return Fliplet.App.Submissions.create({ @@ -681,10 +681,10 @@ function save(origin, submission) { } return cloneCredentialsPromise.then(function () { - Fliplet.App.Submissions.update(newSubmission.id, newSubmission.data).then(function() { + Fliplet.App.Submissions.update(newSubmission.id, newSubmission.data).then(function () { $('.save-' + origin + '-progress').addClass('saved'); - setTimeout(function() { + setTimeout(function () { $('.save-' + origin + '-progress').removeClass('saved'); }, 4000); }); @@ -692,10 +692,10 @@ function save(origin, submission) { }); } - Fliplet.App.Submissions.update(submission.id, submission.data).then(function() { + Fliplet.App.Submissions.update(submission.id, submission.data).then(function () { $('.save-' + origin + '-progress').addClass('saved'); - setTimeout(function() { + setTimeout(function () { $('.save-' + origin + '-progress').removeClass('saved'); }, 4000); }); @@ -731,9 +731,9 @@ function requestBuild(origin, submission) { submission = _.extend(savedSubmission, submission); return Promise.resolve(); }) - .then(function() { + .then(function () { if (submission.status !== 'started') { - if(submission.data.hasOwnProperty('fl-credentials')){ + if (submission.data.hasOwnProperty('fl-credentials')) { delete submission.data['fl-credentials']; } return Fliplet.App.Submissions.create({ @@ -763,7 +763,7 @@ function requestBuild(origin, submission) { certificate: appStorePreviousCredential.certificate, content: appStorePreviousCredential.content }) - .then(function() { + .then(function () { submissionBuild(newSubmission, origin); }); } @@ -780,13 +780,13 @@ function requestBuild(origin, submission) { } return setCertificateP12(appStoreSubmission.id, formData) - .then(function() { + .then(function () { return setCredentials(appStoreSubmission.id, { teamId: teamID, teamName: teamName }); }) - .then(function() { + .then(function () { submissionBuild(newSubmission, origin); }); } @@ -800,7 +800,7 @@ function requestBuild(origin, submission) { certificate: enterprisePreviousCredential.certificate, content: enterprisePreviousCredential.content }) - .then(function() { + .then(function () { submissionBuild(newSubmission, origin); }); } @@ -821,16 +821,16 @@ function requestBuild(origin, submission) { teamId: teamId, teamName: teamName }) - .then(function() { + .then(function () { return setCertificateP12(enterpriseSubmission.id, formData) }) - .then(function() { + .then(function () { return setCredentials(enterpriseSubmission.id, { teamId: teamID, teamName: teamName }); }) - .then(function() { + .then(function () { submissionBuild(newSubmission, origin); }); } @@ -839,7 +839,7 @@ function requestBuild(origin, submission) { }); } - Fliplet.App.Submissions.update(submission.id, submission.data).then(function() { + Fliplet.App.Submissions.update(submission.id, submission.data).then(function () { // Check which type of certificate was given if (origin === "appStore" && appStoreSubmission.data['fl-store-distribution'] === 'previous-file' && appStorePreviousCredential) { return setCredentials(appStoreSubmission.id, { @@ -850,7 +850,7 @@ function requestBuild(origin, submission) { certificate: appStorePreviousCredential.certificate, content: appStorePreviousCredential.content }) - .then(function() { + .then(function () { submissionBuild(submission, origin); }); } @@ -867,13 +867,13 @@ function requestBuild(origin, submission) { } return setCertificateP12(appStoreSubmission.id, formData) - .then(function() { + .then(function () { return setCredentials(appStoreSubmission.id, { teamId: teamID, teamName: teamName }); }) - .then(function() { + .then(function () { submissionBuild(submission, origin); }); } @@ -887,7 +887,7 @@ function requestBuild(origin, submission) { certificate: enterprisePreviousCredential.certificate, content: enterprisePreviousCredential.content }) - .then(function() { + .then(function () { submissionBuild(submission, origin); }); } @@ -904,13 +904,13 @@ function requestBuild(origin, submission) { } return setCertificateP12(enterpriseSubmission.id, formData) - .then(function() { + .then(function () { return setCredentials(enterpriseSubmission.id, { teamId: teamID, teamName: teamName }); }) - .then(function() { + .then(function () { submissionBuild(submission, origin); }); } @@ -1068,7 +1068,7 @@ function saveEnterpriseData(request) { }); } - uploadFilePromise.then(function() { + uploadFilePromise.then(function () { enterpriseSubmission.data = data; notificationSettings = pushData; @@ -1150,7 +1150,7 @@ function savePushData(silentSave) { method: 'PUT', url: 'v1/widget-instances/com.fliplet.push-notifications?appId=' + Fliplet.Env.get('appId'), data: notificationSettings - }).then(function() { + }).then(function () { $('.save-push-progress').addClass('saved'); if (!notificationSettings.apn && !silentSave) { Fliplet.Modal.alert({ @@ -1162,7 +1162,7 @@ function savePushData(silentSave) { }); } - setTimeout(function() { + setTimeout(function () { $('.save-push-progress').removeClass('saved'); }, 4000); }); @@ -1175,7 +1175,7 @@ function cloneCredentials(credentialKey, submission, saveData) { data: { key: submission.data['fl-credentials'] } - }).then(function() { + }).then(function () { if (saveData) { return Fliplet.App.Submissions.update(submission.id, submission.data); } @@ -1216,10 +1216,10 @@ function searchCredentials(data) { } function getAppCredentials(credentialKey, teamId) { - if(credentialKey) { + if (credentialKey) { return getCredential(credentialKey) .then(function(credential) { - if(credential && credential.teamId === teamId && (credential.p12 || credential.certificate)) { + if (credential && credential.teamId === teamId && (credential.p12 || credential.certificate)) { return credential; } @@ -1244,7 +1244,7 @@ function setAppStorePrevCredentials(credential) { } function refreshAppStoreOptions(devEmail, selectedTeamId, selectedTeamName) { - if(!selectedTeamId) { + if (!selectedTeamId) { setAppStorePrevCredentials(); return; } @@ -1252,7 +1252,7 @@ function refreshAppStoreOptions(devEmail, selectedTeamId, selectedTeamName) { return getAppCredentials(appStoreSubmission.data['fl-credentials'], selectedTeamId) .then(function(credential) { - if(credential) { + if (credential) { return credential; } @@ -1273,7 +1273,7 @@ function refreshAppStoreOptions(devEmail, selectedTeamId, selectedTeamName) { }); } - if(credentialKey) { + if (credentialKey) { return getCredential(credentialKey); } @@ -1284,7 +1284,7 @@ function refreshAppStoreOptions(devEmail, selectedTeamId, selectedTeamName) { }); }) .then(function(credential) { - if(credential) { + if (credential) { return credential; } @@ -1295,7 +1295,7 @@ function refreshAppStoreOptions(devEmail, selectedTeamId, selectedTeamName) { } //if we dont have any credentials we need to check previous result for a credential object - if(!_.isUndefined(previousResults) && (!_.isUndefined(previousResults.p12) || !_.isUndefined(previousResults.certificate)) && appStoreSubmission.data['fl-store-teamId'] === selectedTeamId) { + if (!_.isUndefined(previousResults) && (!_.isUndefined(previousResults.p12) || !_.isUndefined(previousResults.certificate)) && appStoreSubmission.data['fl-store-teamId'] === selectedTeamId) { return { teamId: selectedTeamId, teamName: selectedTeamName, @@ -1330,7 +1330,7 @@ function setAppEnterprisePrevCredential(credential) { } function refreshAppEnterpriseOptions(devEmail, selectedTeamId, selectedTeamName) { - if(!selectedTeamId) { + if (!selectedTeamId) { setAppEnterprisePrevCredential(); return; } @@ -1338,7 +1338,7 @@ function refreshAppEnterpriseOptions(devEmail, selectedTeamId, selectedTeamName) return getAppCredentials(enterpriseSubmission.data['fl-credentials'], selectedTeamId) .then(function(credential) { - if(credential) { + if (credential) { return credential; } @@ -1359,7 +1359,7 @@ function refreshAppEnterpriseOptions(devEmail, selectedTeamId, selectedTeamName) }); } - if(credentialKey) { + if (credentialKey) { return getCredential(credentialKey); } @@ -1370,7 +1370,7 @@ function refreshAppEnterpriseOptions(devEmail, selectedTeamId, selectedTeamName) }); }) .then(function(credential) { - if(credential) { + if (credential) { return credential; } @@ -1381,7 +1381,7 @@ function refreshAppEnterpriseOptions(devEmail, selectedTeamId, selectedTeamName) } //if we dont have any credentials we need to check previous result for a credential object - if(!_.isUndefined(previousResults) && (!_.isUndefined(previousResults.p12) || !_.isUndefined(previousResults.certificate)) && enterpriseSubmission.data['fl-ent-teamId'] === selectedTeamId) { + if (!_.isUndefined(previousResults) && (!_.isUndefined(previousResults.p12) || !_.isUndefined(previousResults.certificate)) && enterpriseSubmission.data['fl-ent-teamId'] === selectedTeamId) { return { teamId: selectedTeamId, teamName: selectedTeamName, @@ -1428,7 +1428,7 @@ function getCompletedSubmissions(devEmail, teamId, teamName) { url: url }) .then(function(result) { - if(!result.submissions) { + if (!result.submissions) { return; } @@ -1440,7 +1440,7 @@ function getCompletedSubmissions(devEmail, teamId, teamName) { ) }); - if(!_.isUndefined(latestSubmission)) { + if (!_.isUndefined(latestSubmission)) { return { teamId: teamId, teamName: teamName, @@ -1765,7 +1765,7 @@ function submissionChecker(submissions) { appStoreSubmission.data['fl-credentials'] = 'submission-' + appStoreSubmission.id; - if(previousSubWithCredentials) { + if (previousSubWithCredentials) { cloneAppStoreCredentialsPromise = cloneCredentials(previousSubWithCredentials.data['fl-credentials'], appStoreSubmission, true); } } @@ -1808,7 +1808,7 @@ function submissionChecker(submissions) { enterpriseSubmission.data['fl-credentials'] = 'submission-' + enterpriseSubmission.id; - if(previousSubWithCredentials) { + if (previousSubWithCredentials) { cloneEnterpriseCredentialsPromise = cloneCredentials(previousSubWithCredentials.data['fl-credentials'], enterpriseSubmission, true); } } @@ -1912,7 +1912,7 @@ function getSubmissions() { function initialLoad(initial, timeout) { if (!initial) { - initLoad = setTimeout(function() { + initLoad = setTimeout(function () { getSubmissions() .then(function(submissions) { iosSubmissionChecker(submissions); @@ -1963,7 +1963,7 @@ function initialLoad(initial, timeout) { return submissionChecker(submissions); }); }) - .then(function() { + .then(function () { // Fliplet.Env.get('appId') // Fliplet.Env.get('appName') // Fliplet.Env.get('appSettings') @@ -1987,7 +1987,7 @@ function initialLoad(initial, timeout) { }) ]); }) - .then(function() { + .then(function () { if (appSettings.folderStructure) { var structure = []; hasFolders = true; @@ -2007,7 +2007,7 @@ function initialLoad(initial, timeout) { return Promise.resolve(structure); }); })) - .then(function() { + .then(function () { structure.forEach(function(el, idx) { if (el.type === 'mobile') { screenShotsMobile = el.folderContent.files @@ -2022,7 +2022,7 @@ function initialLoad(initial, timeout) { return; } }) - .then(function() { + .then(function () { return Fliplet.API.request({ method: 'GET', url: 'v1/widget-instances/com.fliplet.push-notifications?appId=' + Fliplet.Env.get('appId') @@ -2097,7 +2097,7 @@ function prompt2FA() { } /* ATTACH LISTENERS */ -$('[name="fl-store-screenshots"]').on('change', function() { +$('[name="fl-store-screenshots"]').on('change', function () { var value = $(this).val(); var id = $(this).attr('id'); checkHasScreenshots(); @@ -2132,7 +2132,7 @@ $('[name="fl-store-screenshots"]').on('change', function() { } }); -$('[name="submissionType"]').on('change', function() { +$('[name="submissionType"]').on('change', function () { var selectedOptionId = $(this).attr('id'); $('.fl-sb-panel').removeClass('show'); @@ -2141,7 +2141,7 @@ $('[name="submissionType"]').on('change', function() { Fliplet.Widget.autosize(); }); -$('[name="fl-store-credentials"]').on('change', function() { +$('[name="fl-store-credentials"]').on('change', function () { var value = $(this).val(); if (value === 'useOwn') { @@ -2153,7 +2153,7 @@ $('[name="fl-store-credentials"]').on('change', function() { Fliplet.Widget.autosize(); }); -$('.fl-sb-appStore [change-bundleid], .fl-sb-enterprise [change-bundleid], .fl-sb-unsigned [change-bundleid]').on('click', function() { +$('.fl-sb-appStore [change-bundleid], .fl-sb-enterprise [change-bundleid], .fl-sb-unsigned [change-bundleid]').on('click', function () { Fliplet.Modal.confirm({ message: 'Are you sure you want to change the unique Bundle ID?' }).then(function (confirmed) { @@ -2169,18 +2169,18 @@ $('.fl-sb-appStore [change-bundleid], .fl-sb-enterprise [change-bundleid], .fl-s }); $('.panel-group') - .on('shown.bs.collapse', '.panel-collapse', function() { + .on('shown.bs.collapse', '.panel-collapse', function () { Fliplet.Widget.autosize(); }) - .on('hidden.bs.collapse', '.panel-collapse', function() { + .on('hidden.bs.collapse', '.panel-collapse', function () { Fliplet.Widget.autosize(); }); $('a[data-toggle="tab"]') - .on('shown.bs.tab', function() { + .on('shown.bs.tab', function () { Fliplet.Widget.autosize(); }) - .on('hidden.bs.tab', function() { + .on('hidden.bs.tab', function () { Fliplet.Widget.autosize(); }); @@ -2230,7 +2230,7 @@ $('[data-change-assets]').on('click', function(event) { }); }); -$('#appStoreConfiguration, #enterpriseConfiguration, #unsignedConfiguration').on('validated.bs.validator', function() { +$('#appStoreConfiguration, #enterpriseConfiguration, #unsignedConfiguration').on('validated.bs.validator', function () { checkGroupErrors(); Fliplet.Widget.autosize(); }); @@ -2276,7 +2276,7 @@ $('#appStoreConfiguration').validator().on('submit', function(event) { return; } - if (certificateKind === 'upload-file' && (!appStoreFileField.files || !appStoreFileField.files[0])){ + if (certificateKind === 'upload-file' && (!appStoreFileField.files || !appStoreFileField.files[0])) { Fliplet.Modal.alert({ message: 'You need to upload a certificate before requesting a submission' }); @@ -2453,21 +2453,21 @@ $('#unsignedConfiguration').validator().on('submit', function(event) { }); /* SAVE PROGRESS CLICK */ -$('[data-app-store-save]').on('click', function() { +$('[data-app-store-save]').on('click', function () { saveAppStoreData(); }); -$('[data-enterprise-save]').on('click', function() { +$('[data-enterprise-save]').on('click', function () { saveEnterpriseData(); }); -$('[data-unsigned-save]').on('click', function() { +$('[data-unsigned-save]').on('click', function () { saveUnsignedData(); }); -$('[data-push-save]').on('click', function() { +$('[data-push-save]').on('click', function () { savePushData(); }); /* Credentials and Certificates App Store */ -$('.login-appStore-button').on('click', function() { +$('.login-appStore-button').on('click', function () { var $this = $(this); $(this).html('Logging in' + spinner); $(this).addClass('disabled'); @@ -2506,7 +2506,7 @@ $('.login-appStore-button').on('click', function() { email: devEmail, password: devPass }) - .then(function() { + .then(function () { $this.html('Log in'); $this.removeClass('disabled'); return appStoreTeamSetup(devEmail, true); @@ -2532,11 +2532,11 @@ $('.login-appStore-button').on('click', function() { } }); -$('.log-out-appStore').on('click', function() { +$('.log-out-appStore').on('click', function () { clearAppStoreCredentials(); }); -$('[name="fl-store-distribution"]').on('change', function() { +$('[name="fl-store-distribution"]').on('change', function () { var value = $(this).val(); $('#fl-store-teams').prop('required',true); @@ -2597,7 +2597,7 @@ $('#fl-load-store-teams').on('click', function (e) { }); }); -$('#fl-store-teams').on('change', function() { +$('#fl-store-teams').on('change', function () { var value = $(this).val(); var teamName = value ? $('#fl-store-teams').find(":selected").data('team-name') : ''; @@ -2615,7 +2615,7 @@ $('#fl-store-teams').on('change', function() { return refreshAppStoreOptions(devEmail, value, teamName); }); -$('.appStore-generate-cert').on('click', function() { +$('.appStore-generate-cert').on('click', function () { var $this = $(this); $(this).html('Generating' + spinner); $(this).addClass('disabled'); @@ -2628,7 +2628,7 @@ $('.appStore-generate-cert').on('click', function() { teamId: teamId, teamName: teamName }) - .then(function() { + .then(function () { return createCertificates({ organizationId: organizationID, submissionId: appStoreSubmission.id @@ -2653,7 +2653,7 @@ $('.appStore-generate-cert').on('click', function() { }); }); -$('#fl-store-certificate').on('change', function() { +$('#fl-store-certificate').on('change', function () { appStoreFileField = this; var fileName = appStoreFileField.value.replace(/\\/g, '/').replace(/.*\//, ''); @@ -2662,7 +2662,7 @@ $('#fl-store-certificate').on('change', function() { } }); -$('.appStore-replace-cert').on('click', function() { +$('.appStore-replace-cert').on('click', function () { var $this = $(this); $(this).html('Replacing' + spinner); $(this).addClass('disabled'); @@ -2673,12 +2673,12 @@ $('.appStore-replace-cert').on('click', function() { if (appStorePreviousCredential.certificate && appStorePreviousCredential.certificate.id) { return revokeCertificate(appStoreSubmission.id, appStorePreviousCredential.certificate.id) - .then(function() { + .then(function () { return setCredentials(appStoreSubmission.id, { teamId: teamId, teamName: teamName }) - .then(function() { + .then(function () { return createCertificates({ organizationId: organizationID, submissionId: appStoreSubmission.id @@ -2710,7 +2710,7 @@ $('.appStore-replace-cert').on('click', function() { /**/ /* Credentials and Certificates Enterprise */ -$('.login-enterprise-button').on('click', function() { +$('.login-enterprise-button').on('click', function () { var $this = $(this); $(this).html('Logging in' + spinner); $(this).addClass('disabled'); @@ -2749,7 +2749,7 @@ $('.login-enterprise-button').on('click', function() { email: devEmail, password: devPass }) - .then(function() { + .then(function () { $('[name="fl-ent-distribution"][value="generate-file"]').prop('checked', true).trigger('change'); $this.html('Log in'); $this.removeClass('disabled'); @@ -2776,11 +2776,11 @@ $('.login-enterprise-button').on('click', function() { } }); -$('.log-out-enterprise').on('click', function() { +$('.log-out-enterprise').on('click', function () { clearEnterpriseCredentials(); }); -$('[name="fl-ent-distribution"]').on('change', function() { +$('[name="fl-ent-distribution"]').on('change', function () { var value = $(this).val(); $('#fl-ent-teams').prop('required',true); @@ -2838,7 +2838,7 @@ $('#fl-load-ent-teams').on('click', function (e) { }); }); -$('#fl-ent-teams').on('change', function() { +$('#fl-ent-teams').on('change', function () { var value = $(this).val(); var teamName = value ? $('#fl-ent-teams').find(":selected").data('team-name') : ''; @@ -2856,7 +2856,7 @@ $('#fl-ent-teams').on('change', function() { return refreshAppEnterpriseOptions(devEmail, value, teamName); }); -$('.enterprise-generate-cert').on('click', function() { +$('.enterprise-generate-cert').on('click', function () { var $this = $(this); $(this).html('Generating' + spinner); $(this).addClass('disabled'); @@ -2869,7 +2869,7 @@ $('.enterprise-generate-cert').on('click', function() { teamId: teamId, teamName: teamName }) - .then(function() { + .then(function () { return createCertificates({ organizationId: organizationID, submissionId: enterpriseSubmission.id, @@ -2895,7 +2895,7 @@ $('.enterprise-generate-cert').on('click', function() { }); }); -$('#fl-ent-certificate').on('change', function() { +$('#fl-ent-certificate').on('change', function () { enterpriseFileField = this; var fileName = enterpriseFileField.value.replace(/\\/g, '/').replace(/.*\//, ''); @@ -2904,7 +2904,7 @@ $('#fl-ent-certificate').on('change', function() { } }); -$('#fl-ent-certificate-manual-details').on('change', function() { +$('#fl-ent-certificate-manual-details').on('change', function () { enterpriseFileFieldManual = this; var fileName = enterpriseFileFieldManual.value.replace(/\\/g, '/').replace(/.*\//, ''); @@ -2913,7 +2913,7 @@ $('#fl-ent-certificate-manual-details').on('change', function() { } }); -$('#fl-ent-mobileprovision-manual-details').on('change', function() { +$('#fl-ent-mobileprovision-manual-details').on('change', function () { enterpriseFileProvisionFieldManual = this; var fileName = enterpriseFileProvisionFieldManual.value.replace(/\\/g, '/').replace(/.*\//, ''); @@ -2922,7 +2922,7 @@ $('#fl-ent-mobileprovision-manual-details').on('change', function() { } }); -$('.enterprise-replace-cert').on('click', function() { +$('.enterprise-replace-cert').on('click', function () { var $this = $(this); $(this).html('Replacing' + spinner); $(this).addClass('disabled'); @@ -2933,12 +2933,12 @@ $('.enterprise-replace-cert').on('click', function() { if (enterprisePreviousCredential.certificate && enterprisePreviousCredential.certificate.id) { return revokeCertificate(enterpriseSubmission.id, enterprisePreviousCredential.certificate.id) - .then(function() { + .then(function () { return setCredentials(enterpriseSubmission.id, { teamId: teamId, teamName: teamName }) - .then(function() { + .then(function () { return createCertificates({ organiazationId: organizationID, submissionId: enterpriseSubmission.id, @@ -2969,7 +2969,7 @@ $('.enterprise-replace-cert').on('click', function() { } }); -$('.ent-enter-manually').on('click', function() { +$('.ent-enter-manually').on('click', function () { $('.enterprise-login-details').addClass('hidden'); $('.enterprise-manual-details').addClass('show'); enterpriseManual = true; @@ -2984,7 +2984,7 @@ $('.ent-enter-manually').on('click', function() { $('#fl-ent-mobileprovision-manual-details').prop('required', true); }); -$('.enterprise-back-login').on('click', function() { +$('.enterprise-back-login').on('click', function () { $('.enterprise-login-details').removeClass('hidden'); $('.enterprise-manual-details').removeClass('show'); enterpriseManual = false; @@ -3000,14 +3000,14 @@ $('.enterprise-back-login').on('click', function() { }); /**/ -$(document).on('click', '[data-cancel-build-id]', function() { +$(document).on('click', '[data-cancel-build-id]', function () { var buildId = $(this).data('cancel-build-id'); Fliplet.API.request({ method: 'DELETE', url: 'v1/apps/' + Fliplet.Env.get('appId') + '/submissions/' + buildId }) - .then(function() { + .then(function () { clearTimeout(initLoad); initialLoad(false, 0); }) From 45049b6fc0a65837965e34aba0fc88bfe13070e8 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Fri, 22 Feb 2019 14:59:34 +0000 Subject: [PATCH 120/318] Spaces --- js/interface.js | 240 ++++++++++++++++++++++++------------------------ 1 file changed, 120 insertions(+), 120 deletions(-) diff --git a/js/interface.js b/js/interface.js index 48f305c..f244051 100644 --- a/js/interface.js +++ b/js/interface.js @@ -49,7 +49,7 @@ var socket = Fliplet.Socket({ /* FUNCTIONS */ String.prototype.toCamelCase = function () { - return this.replace(/^([A-Z])|[^A-Za-z]+(\w)/g, function(match, p1, p2, offset) { + return this.replace(/^([A-Z])|[^A-Za-z]+(\w)/g, function (match, p1, p2, offset) { if (p2) return p2.toUpperCase(); return p1.toLowerCase(); }).replace(/([^A-Z-a-z])/g, '').toLowerCase(); @@ -86,7 +86,7 @@ function addThumb(thumb) { } function loadAppStoreData() { - $('#appStoreConfiguration [name]').each(function(i, el) { + $('#appStoreConfiguration [name]').each(function (i, el) { var name = $(el).attr("name"); var hasAppId = !_.isUndefined(appStoreSubmission.data['iTunesAppId']); @@ -149,7 +149,7 @@ function loadAppStoreData() { /* ADD BUNDLE ID */ if (name === "fl-store-bundleId" && typeof appStoreSubmission.data[name] === "undefined") { - createBundleID(organizationName.toCamelCase(), appName.toCamelCase()).then(function(response) { + createBundleID(organizationName.toCamelCase(), appName.toCamelCase()).then(function (response) { if (response.resultCount === 0) { $('.bundleId-ast-text').html('com.' + organizationName.toCamelCase() + '.' + appName.toCamelCase()); $('[name="' + name + '"]').val('com.' + organizationName.toCamelCase() + '.' + appName.toCamelCase()); @@ -301,8 +301,8 @@ function loadAppStoreTeams(devEmail) { var itunesTeams = teams[0]; var appStoreTeams = teams[1]; - appStoreTeams = _.filter(appStoreTeams, function(team) { - var itunesTeam = _.find(itunesTeams, function(itcTeam) { + appStoreTeams = _.filter(appStoreTeams, function (team) { + var itunesTeam = _.find(itunesTeams, function (itcTeam) { return itcTeam.team_name === team.name; }); @@ -310,7 +310,7 @@ function loadAppStoreTeams(devEmail) { }); var options = ['']; - appStoreTeams.forEach(function(team, i) { + appStoreTeams.forEach(function (team, i) { options.push(''); }); $('#fl-load-store-teams').hide(); @@ -349,12 +349,12 @@ function appStoreTeamSetup(devEmail, loadTeams) { } function loadEnterpriseData() { - $('#enterpriseConfiguration [name]').each(function(i, el) { + $('#enterpriseConfiguration [name]').each(function (i, el) { var name = $(el).attr("name"); /* ADD BUNDLE ID */ if (name === "fl-ent-bundleId" && typeof enterpriseSubmission.data[name] === "undefined") { - createBundleID(organizationName.toCamelCase(), appName.toCamelCase()).then(function(response) { + createBundleID(organizationName.toCamelCase(), appName.toCamelCase()).then(function (response) { if (response.resultCount === 0) { $('.bundleId-ent-text').html('com.' + organizationName.toCamelCase() + '.' + appName.toCamelCase()); $('[name="' + name + '"]').val('com.' + organizationName.toCamelCase() + '.' + appName.toCamelCase()); @@ -467,12 +467,12 @@ function clearEnterpriseCredentials() { function loadEnterpriseTeams(devEmail) { return getTeams(enterpriseSubmission.id, false) - .then(function(teams) { - var enterpriseTeams = _.filter(teams, function(team) { + .then(function (teams) { + var enterpriseTeams = _.filter(teams, function (team) { return team.type === "In-House"; }) var options = ['']; - enterpriseTeams.forEach(function(team, i) { + enterpriseTeams.forEach(function (team, i) { options.push(''); }); $('#fl-load-ent-teams').hide(); @@ -511,12 +511,12 @@ function enterpriseTeamSetup(devEmail, loadTeams) { } function loadUnsignedData() { - $('#unsignedConfiguration [name]').each(function(i, el) { + $('#unsignedConfiguration [name]').each(function (i, el) { var name = $(el).attr("name"); /* ADD BUNDLE ID */ if (name === "fl-uns-bundleId" && typeof unsignedSubmission.data[name] === "undefined") { - createBundleID(organizationName.toCamelCase(), appName.toCamelCase()).then(function(response) { + createBundleID(organizationName.toCamelCase(), appName.toCamelCase()).then(function (response) { if (response.resultCount === 0) { $('.bundleId-uns-text').html('com.' + organizationName.toCamelCase() + '.' + appName.toCamelCase()); $('[name="' + name + '"]').val('com.' + organizationName.toCamelCase() + '.' + appName.toCamelCase()); @@ -568,7 +568,7 @@ function loadUnsignedData() { function loadPushNotesData() { - $('#pushConfiguration [name]').each(function(i, el) { + $('#pushConfiguration [name]').each(function (i, el) { var name = $(el).attr("name"); // ADDING NOTIFICATIONS SETTINGS @@ -584,7 +584,7 @@ function loadPushNotesData() { } function submissionBuild(appSubmission, origin) { - Fliplet.App.Submissions.build(appSubmission.id).then(function(builtSubmission) { + Fliplet.App.Submissions.build(appSubmission.id).then(function (builtSubmission) { if (origin === "appStore") { appStoreSubmission = builtSubmission.submission; @@ -631,7 +631,7 @@ function submissionBuild(appSubmission, origin) { Fliplet.Widget.autosize(); }); }, 10000); - }, function(err) { + }, function (err) { $('.button-' + origin + '-request').html('Request App '); $('.button-' + origin + '-request').prop('disabled', false); Fliplet.Modal.alert({ @@ -643,8 +643,8 @@ function submissionBuild(appSubmission, origin) { function save(origin, submission) { Fliplet.App.Submissions.get() - .then(function(submissions) { - var savedSubmission = _.find(submissions, function(sub) { + .then(function (submissions) { + var savedSubmission = _.find(submissions, function (sub) { return sub.id === submission.id; }); @@ -663,7 +663,7 @@ function save(origin, submission) { previousResults: submission.result }) }) - .then(function(newSubmission) { + .then(function (newSubmission) { var cloneCredentialsPromise = Promise.resolve(); if (origin === "appStore") { @@ -700,7 +700,7 @@ function save(origin, submission) { }, 4000); }); }) - .catch(function(err) { + .catch(function (err) { Fliplet.Modal.alert({ message: Fliplet.parseError(err) }); @@ -723,8 +723,8 @@ function requestBuild(origin, submission) { submission.data.legacyBuild = appSettings.legacyBuild || false; Fliplet.App.Submissions.get() - .then(function(submissions) { - var savedSubmission = _.find(submissions, function(sub) { + .then(function (submissions) { + var savedSubmission = _.find(submissions, function (sub) { return sub.id === submission.id; }); @@ -742,7 +742,7 @@ function requestBuild(origin, submission) { previousResults: submission.result }) }) - .then(function(newSubmission) { + .then(function (newSubmission) { if (origin === "appStore") { appStoreSubmission = newSubmission; } @@ -918,7 +918,7 @@ function requestBuild(origin, submission) { submissionBuild(submission, origin); }); }) - .catch(function(err) { + .catch(function (err) { $('.button-' + origin + '-request').html('Request App '); $('.button-' + origin + '-request').prop('disabled', false); Fliplet.Modal.alert({ @@ -931,7 +931,7 @@ function saveAppStoreData(request) { var data = appStoreSubmission.data; var pushData = notificationSettings; - $('#appStoreConfiguration [name]').each(function(i, el) { + $('#appStoreConfiguration [name]').each(function (i, el) { var name = $(el).attr("name"); var value = $(el).val(); @@ -998,7 +998,7 @@ function saveEnterpriseData(request) { var pushData = notificationSettings; var uploadFilePromise = Promise.resolve(); - $('#enterpriseConfiguration [name]').each(function(i, el) { + $('#enterpriseConfiguration [name]').each(function (i, el) { var name = $(el).attr("name"); var value = $(el).val(); @@ -1062,7 +1062,7 @@ function saveEnterpriseData(request) { uploadFilePromise = Fliplet.Media.Files.upload({ data: file, appId: Fliplet.Env.get('appId') - }).then(function(files) { + }).then(function (files) { data['fl-ent-certificate-files'] = files; return Promise.resolve(); }); @@ -1100,7 +1100,7 @@ function saveEnterpriseData(request) { function saveUnsignedData(request) { var data = unsignedSubmission.data; - $('#unsignedConfiguration [name]').each(function(i, el) { + $('#unsignedConfiguration [name]').each(function (i, el) { var name = $(el).attr("name"); var value = $(el).val(); @@ -1127,7 +1127,7 @@ function savePushData(silentSave) { 'fl-push-keyId': 'apnKeyId' }; - $('#pushConfiguration [name]').each(function(i, el) { + $('#pushConfiguration [name]').each(function (i, el) { var name = $(el).attr("name"); if (!pushDataMap.hasOwnProperty(name)) { @@ -1199,7 +1199,7 @@ function getTeams(id, isItunes) { method: 'GET', url: 'v1/organizations/' + organizationID + '/credentials/submission-' + id + '/teams?itunes=' + isItunes }) - .then(function(result) { + .then(function (result) { return Promise.resolve(result.teams); }); } @@ -1210,7 +1210,7 @@ function searchCredentials(data) { url: 'v1/organizations/' + organizationID + '/credentials/search', data: data }) - .then(function(credentials) { + .then(function (credentials) { return Promise.resolve(credentials); }); } @@ -1218,7 +1218,7 @@ function searchCredentials(data) { function getAppCredentials(credentialKey, teamId) { if (credentialKey) { return getCredential(credentialKey) - .then(function(credential) { + .then(function (credential) { if (credential && credential.teamId === teamId && (credential.p12 || credential.certificate)) { return credential; } @@ -1251,7 +1251,7 @@ function refreshAppStoreOptions(devEmail, selectedTeamId, selectedTeamName) { return getAppCredentials(appStoreSubmission.data['fl-credentials'], selectedTeamId) - .then(function(credential) { + .then(function (credential) { if (credential) { return credential; } @@ -1261,7 +1261,7 @@ function refreshAppStoreOptions(devEmail, selectedTeamId, selectedTeamName) { type: 'apple', teamId: selectedTeamId }) - .then(function(response) { + .then(function (response) { var credentialKey; var submissionsWithCred = _.filter(Object.keys(response), function (o) { return response[o].hasCertificate === true; @@ -1279,11 +1279,11 @@ function refreshAppStoreOptions(devEmail, selectedTeamId, selectedTeamName) { return; }) - .catch(function(error) { + .catch(function (error) { return; }); }) - .then(function(credential) { + .then(function (credential) { if (credential) { return credential; } @@ -1308,10 +1308,10 @@ function refreshAppStoreOptions(devEmail, selectedTeamId, selectedTeamName) { return getCompletedSubmissions(devEmail, selectedTeamId, selectedTeamName); }) - .then(function(credential) { + .then(function (credential) { return setAppStorePrevCredentials(credential); }) - .catch(function(error) { + .catch(function (error) { return setAppStorePrevCredentials(); }); } @@ -1337,7 +1337,7 @@ function refreshAppEnterpriseOptions(devEmail, selectedTeamId, selectedTeamName) return getAppCredentials(enterpriseSubmission.data['fl-credentials'], selectedTeamId) - .then(function(credential) { + .then(function (credential) { if (credential) { return credential; } @@ -1347,7 +1347,7 @@ function refreshAppEnterpriseOptions(devEmail, selectedTeamId, selectedTeamName) type: 'apple-enterprise', teamId: selectedTeamId }) - .then(function(response) { + .then(function (response) { var credentialKey; var submissionsWithCred = _.filter(Object.keys(response), function (o) { return response[o].hasCertificate === true; @@ -1365,11 +1365,11 @@ function refreshAppEnterpriseOptions(devEmail, selectedTeamId, selectedTeamName) return; }) - .catch(function(error) { + .catch(function (error) { return; }); }) - .then(function(credential) { + .then(function (credential) { if (credential) { return credential; } @@ -1394,10 +1394,10 @@ function refreshAppEnterpriseOptions(devEmail, selectedTeamId, selectedTeamName) return getCompletedSubmissions(devEmail, selectedTeamId, selectedTeamName); }) - .then(function(credential) { + .then(function (credential) { return setAppEnterprisePrevCredential(credential); }) - .catch(function(error) { + .catch(function (error) { return setAppEnterprisePrevCredential(); }); } @@ -1414,7 +1414,7 @@ function getCompletedSubmissions(devEmail, teamId, teamName) { 'failed', // CI failed 'cancelled' // user canceled ]; - var statusFilter = _.filter(statusList, function(s) { + var statusFilter = _.filter(statusList, function (s) { return s !== 'failed'; }); var url = [ @@ -1427,13 +1427,13 @@ function getCompletedSubmissions(devEmail, teamId, teamName) { method: 'GET', url: url }) - .then(function(result) { + .then(function (result) { if (!result.submissions) { return; } var sortedSubmissions = _.orderBy(result.submissions, ['updatedAt'], ['desc']); - var latestSubmission = _.find(sortedSubmissions, function(sub) { + var latestSubmission = _.find(sortedSubmissions, function (sub) { return !_.isUndefined(sub.data.previousResults) && (!_.isUndefined(sub.data.previousResults.p12) || !_.isUndefined(sub.data.previousResults.certificate) @@ -1460,7 +1460,7 @@ function getCredential(credentialKey) { method: 'GET', url: 'v1/organizations/' + organizationID + '/credentials/' + credentialKey }) - .then(function(credential) { + .then(function (credential) { if (!credential || !credential.email) { // Valid credential email not found return Promise.resolve(); @@ -1487,7 +1487,7 @@ function createCertificates(options) { inHouse: options.inHouse } }) - .then(function(credential) { + .then(function (credential) { return Promise.resolve(credential); }); } @@ -1510,8 +1510,8 @@ function revokeCertificate(id, certId) { } function init() { - Fliplet.Apps.get().then(function(apps) { - appInfo = _.find(apps, function(app) { + Fliplet.Apps.get().then(function (apps) { + appInfo = _.find(apps, function (app) { return app.id === Fliplet.Env.get('appId'); }); }); @@ -1541,11 +1541,11 @@ function init() { /* AUX FUNCTIONS */ function checkGroupErrors() { - $('.has-error').each(function(i, el) { + $('.has-error').each(function (i, el) { $(el).parents('.panel-default').addClass('required-fill'); }); - $('.panel-default').each(function(i, el) { + $('.panel-default').each(function (i, el) { var withError = $(el).find('.has-error').length; if (withError === 0) { @@ -1559,8 +1559,8 @@ function validateScreenshots() { var supportedFormats = [[1242,2208], [2048,2732], [2732,2048]]; var allScreenShots = _.concat(screenShotsMobile, screenShotsTablet); - _.forEach(allScreenShots, function(screenshot, key) { - var supportedSize = _.find(supportedFormats, function(format) { + _.forEach(allScreenShots, function (screenshot, key) { + var supportedSize = _.find(supportedFormats, function (format) { return format[0] === screenshot.size[0] && format[1] === screenshot.size[1]; }); @@ -1593,7 +1593,7 @@ function publishApp(context) { method: 'POST', url: 'v1/apps/' + Fliplet.Env.get('appId') + '/publish', data: options - }).then(function(response) { + }).then(function (response) { // Update appInfo appInfo.productionAppId = response.app.id; @@ -1652,13 +1652,13 @@ function compileStatusTable(withData, origin, buildsData) { } function checkSubmissionStatus(origin, iosSubmissions) { - var submissionsToShow = _.filter(iosSubmissions, function(submission) { + var submissionsToShow = _.filter(iosSubmissions, function (submission) { return submission.status === "queued" || submission.status === "submitted" || submission.status === "processing" || submission.status === "completed" || submission.status === "failed" || submission.status === "cancelled" || submission.status === "ready-for-testing" || submission.status === "tested"; }); var buildsData = []; if (submissionsToShow.length) { - submissionsToShow.forEach(function(submission) { + submissionsToShow.forEach(function (submission) { var build = {}; var appBuild; var debugHtmlPage; @@ -1677,21 +1677,21 @@ function checkSubmissionStatus(origin, iosSubmissions) { } if (submission.result.appBuild && submission.result.appBuild.files) { - appBuild = _.find(submission.result.appBuild.files, function(file) { + appBuild = _.find(submission.result.appBuild.files, function (file) { return file.contentType === 'application/octet-stream'; }); } else if (submission.data.previousResults && submission.data.previousResults.appBuild && submission.data.previousResults.appBuild.files) { - appBuild = _.find(submission.data.previousResults.appBuild.files, function(file) { + appBuild = _.find(submission.data.previousResults.appBuild.files, function (file) { return file.contentType === 'application/octet-stream'; }); } if (submission.result.debugHtmlPage && submission.result.debugHtmlPage.files) { - debugHtmlPage = _.find(submission.result.debugHtmlPage.files, function(file) { + debugHtmlPage = _.find(submission.result.debugHtmlPage.files, function (file) { return file.contentType === 'text/html'; }); } else if (submission.data.previousResults && submission.data.previousResults.debugHtmlPage && submission.data.previousResults.debugHtmlPage.files) { - debugHtmlPage = _.find(submission.data.previousResults.debugHtmlPage.files, function(file) { + debugHtmlPage = _.find(submission.data.previousResults.debugHtmlPage.files, function (file) { return file.contentType === 'text/html'; }); } @@ -1724,27 +1724,27 @@ function checkSubmissionStatus(origin, iosSubmissions) { } function submissionChecker(submissions) { - var asub = _.filter(submissions, function(submission) { + var asub = _.filter(submissions, function (submission) { return submission.data.submissionType === "appStore" && submission.platform === "ios"; }); - var completedAsub = _.filter(asub, function(submission) { + var completedAsub = _.filter(asub, function (submission) { return submission.status === "completed"; }); //Get the Submission data from the first completed submission, it has the certification values that are in use on the app store. - previousAppStoreSubmission = _.minBy(completedAsub, function(el) { + previousAppStoreSubmission = _.minBy(completedAsub, function (el) { return el.id; }); appStoreSubmissionInStore = (completedAsub.length > 0); - asub = _.orderBy(asub, function(submission) { + asub = _.orderBy(asub, function (submission) { return new Date(submission.createdAt).getTime(); }, ['desc']); checkSubmissionStatus("appStore", asub); - appStoreSubmission = _.maxBy(asub, function(el) { + appStoreSubmission = _.maxBy(asub, function (el) { return new Date(el.createdAt).getTime(); }); @@ -1755,11 +1755,11 @@ function submissionChecker(submissions) { var cloneAppStoreCredentialsPromise = Promise.resolve(); if (appStoreSubmission.data && !appStoreSubmission.data['fl-credentials']) { - var prevSubCred = _.filter(asub, function(submission) { + var prevSubCred = _.filter(asub, function (submission) { return submission.data && submission.data['fl-credentials']; }); - var previousSubWithCredentials = _.maxBy(prevSubCred, function(el) { + var previousSubWithCredentials = _.maxBy(prevSubCred, function (el) { return new Date(el.createdAt).getTime(); }); @@ -1770,24 +1770,24 @@ function submissionChecker(submissions) { } } - var esub = _.filter(submissions, function(submission) { + var esub = _.filter(submissions, function (submission) { return submission.data.submissionType === "enterprise" && submission.platform === "ios"; }); - var completedEsub = _.filter(esub, function(submission) { + var completedEsub = _.filter(esub, function (submission) { return submission.status === "completed"; }); //Get the Submission data from the first completed submission, it has certification values that are in use on the developer portal. - previousEnterpriseStoreSubmission = _.minBy(completedEsub, function(el) { + previousEnterpriseStoreSubmission = _.minBy(completedEsub, function (el) { return el.id; }); - esub = _.orderBy(esub, function(submission) { + esub = _.orderBy(esub, function (submission) { return new Date(submission.createdAt).getTime(); }, ['desc']); checkSubmissionStatus("enterprise", esub); - enterpriseSubmission = _.maxBy(esub, function(el) { + enterpriseSubmission = _.maxBy(esub, function (el) { return new Date(el.createdAt).getTime(); }); @@ -1798,11 +1798,11 @@ function submissionChecker(submissions) { var cloneEnterpriseCredentialsPromise = Promise.resolve(); if (enterpriseSubmission.data && !enterpriseSubmission.data['fl-credentials']) { - var prevSubCred = _.filter(esub, function(submission) { + var prevSubCred = _.filter(esub, function (submission) { return submission.data && submission.data['fl-credentials']; }); - var previousSubWithCredentials = _.maxBy(prevSubCred, function(el) { + var previousSubWithCredentials = _.maxBy(prevSubCred, function (el) { return new Date(el.createdAt).getTime(); }); @@ -1813,16 +1813,16 @@ function submissionChecker(submissions) { } } - var usub = _.filter(submissions, function(submission) { + var usub = _.filter(submissions, function (submission) { return submission.data.submissionType === "unsigned" && submission.platform === "ios"; }); - usub = _.orderBy(usub, function(submission) { + usub = _.orderBy(usub, function (submission) { return new Date(submission.createdAt).getTime(); }, ['desc']); checkSubmissionStatus("unsigned", usub); - usub = _.maxBy(usub, function(el) { + usub = _.maxBy(usub, function (el) { return new Date(el.createdAt).getTime(); }); unsignedSubmission = usub; @@ -1837,7 +1837,7 @@ function submissionChecker(submissions) { submissionType: "appStore" } }) - .then(function(submission) { + .then(function (submission) { appStoreSubmission = submission; return Promise.resolve(); }); @@ -1852,7 +1852,7 @@ function submissionChecker(submissions) { submissionType: "enterprise" } }) - .then(function(submission) { + .then(function (submission) { enterpriseSubmission = submission; return Promise.resolve(); }); @@ -1867,7 +1867,7 @@ function submissionChecker(submissions) { submissionType: "unsigned" } }) - .then(function(submission) { + .then(function (submission) { unsignedSubmission = submission; return Promise.resolve(); }); @@ -1878,26 +1878,26 @@ function submissionChecker(submissions) { } function iosSubmissionChecker(submissions) { - var asub = _.filter(submissions, function(submission) { + var asub = _.filter(submissions, function (submission) { return submission.data.submissionType === "appStore" && submission.platform === "ios"; }); - var esub = _.filter(submissions, function(submission) { + var esub = _.filter(submissions, function (submission) { return submission.data.submissionType === "enterprise" && submission.platform === "ios"; }); - var usub = _.filter(submissions, function(submission) { + var usub = _.filter(submissions, function (submission) { return submission.data.submissionType === "unsigned" && submission.platform === "ios"; }); // Ordering - asub = _.orderBy(asub, function(submission) { + asub = _.orderBy(asub, function (submission) { return new Date(submission.createdAt).getTime(); }, ['desc']); - esub = _.orderBy(esub, function(submission) { + esub = _.orderBy(esub, function (submission) { return new Date(submission.createdAt).getTime(); }, ['desc']); - usub = _.orderBy(usub, function(submission) { + usub = _.orderBy(usub, function (submission) { return new Date(submission.createdAt).getTime(); }, ['desc']); @@ -1914,14 +1914,14 @@ function initialLoad(initial, timeout) { if (!initial) { initLoad = setTimeout(function () { getSubmissions() - .then(function(submissions) { + .then(function (submissions) { iosSubmissionChecker(submissions); initialLoad(false, 15000); }); }, timeout); } else { getSubmissions() - .then(function(submissions) { + .then(function (submissions) { if (!submissions.length) { return Promise.all([ Fliplet.App.Submissions.create({ @@ -1930,7 +1930,7 @@ function initialLoad(initial, timeout) { submissionType: "appStore" } }) - .then(function(submission) { + .then(function (submission) { appStoreSubmission = submission; }), Fliplet.App.Submissions.create({ @@ -1939,7 +1939,7 @@ function initialLoad(initial, timeout) { submissionType: "unsigned" } }) - .then(function(submission) { + .then(function (submission) { unsignedSubmission = submission; }), Fliplet.App.Submissions.create({ @@ -1948,7 +1948,7 @@ function initialLoad(initial, timeout) { submissionType: "enterprise" } }) - .then(function(submission) { + .then(function (submission) { enterpriseSubmission = submission; }) ]); @@ -1958,7 +1958,7 @@ function initialLoad(initial, timeout) { cache: true, url: 'v1/user' }) - .then(function(user) { + .then(function (user) { userInfo = user; return submissionChecker(submissions); }); @@ -1973,7 +1973,7 @@ function initialLoad(initial, timeout) { method: 'GET', url: 'v1/apps/' + Fliplet.Env.get('appId') }) - .then(function(result) { + .then(function (result) { appName = result.app.name; appIcon = result.app.icon; appSettings = result.app.settings; @@ -1982,7 +1982,7 @@ function initialLoad(initial, timeout) { method: 'GET', url: 'v1/organizations/' + organizationID }) - .then(function(org) { + .then(function (org) { organizationName = org.name; }) ]); @@ -1991,13 +1991,13 @@ function initialLoad(initial, timeout) { if (appSettings.folderStructure) { var structure = []; hasFolders = true; - var appleOnly = _.filter(appSettings.folderStructure, function(obj) { + var appleOnly = _.filter(appSettings.folderStructure, function (obj) { return obj.platform === 'apple'; }); - return Promise.all(appleOnly.map(function(obj) { + return Promise.all(appleOnly.map(function (obj) { return Fliplet.Media.Folders.get({folderId: obj.folderId}) - .then(function(result) { + .then(function (result) { var tempObject = { type: obj.type, folderContent: result @@ -2008,7 +2008,7 @@ function initialLoad(initial, timeout) { }); })) .then(function () { - structure.forEach(function(el, idx) { + structure.forEach(function (el, idx) { if (el.type === 'mobile') { screenShotsMobile = el.folderContent.files } @@ -2028,7 +2028,7 @@ function initialLoad(initial, timeout) { url: 'v1/widget-instances/com.fliplet.push-notifications?appId=' + Fliplet.Env.get('appId') }); }) - .then(function(response) { + .then(function (response) { if (response.widgetInstance.settings && response.widgetInstance.settings) { notificationSettings = response.widgetInstance.settings; } else { @@ -2115,11 +2115,11 @@ $('[name="fl-store-screenshots"]').on('change', function () { $('[data-item="fl-store-screenshots-existing"]').removeClass('show'); - _.take(screenShotsMobile, 4).forEach(function(thumb) { + _.take(screenShotsMobile, 4).forEach(function (thumb) { $('.mobile-thumbs').append(addThumb(thumb)); }); - _.take(screenShotsTablet, 4).forEach(function(thumb) { + _.take(screenShotsTablet, 4).forEach(function (thumb) { $('.tablet-thumbs').append(addThumb(thumb)); }); } @@ -2184,7 +2184,7 @@ $('a[data-toggle="tab"]') Fliplet.Widget.autosize(); }); -$('[name="fl-store-keywords"]').on('tokenfield:createtoken', function(e) { +$('[name="fl-store-keywords"]').on('tokenfield:createtoken', function (e) { var currentValue = e.currentTarget.value.replace(/,\s+/g, ','); var newValue = e.attrs.value; var oldAndNew = currentValue + ',' + newValue; @@ -2194,7 +2194,7 @@ $('[name="fl-store-keywords"]').on('tokenfield:createtoken', function(e) { } }); -$('.redirectToSettings, [data-change-settings]').on('click', function(event) { +$('.redirectToSettings, [data-change-settings]').on('click', function (event) { event.preventDefault(); Fliplet.Studio.emit('close-overlay', { @@ -2212,7 +2212,7 @@ $('.redirectToSettings, [data-change-settings]').on('click', function(event) { }); }); -$('[data-change-assets]').on('click', function(event) { +$('[data-change-assets]').on('click', function (event) { event.preventDefault(); Fliplet.Studio.emit('close-overlay', { @@ -2235,7 +2235,7 @@ $('#appStoreConfiguration, #enterpriseConfiguration, #unsignedConfiguration').on Fliplet.Widget.autosize(); }); -$('#appStoreConfiguration').validator().on('submit', function(event) { +$('#appStoreConfiguration').validator().on('submit', function (event) { if (_.includes(['fl-store-appDevLogin', 'fl-store-appDevPass'], document.activeElement.id)) { // User submitted app store login form $('.login-appStore-button').trigger('click'); @@ -2323,7 +2323,7 @@ $('#appStoreConfiguration').validator().on('submit', function(event) { setTimeout(checkGroupErrors, 0); }); -$('#enterpriseConfiguration').validator().on('submit', function(event) { +$('#enterpriseConfiguration').validator().on('submit', function (event) { if (_.includes(['fl-ent-appDevLogin', 'fl-ent-appDevPass'], document.activeElement.id)) { // User submitted enterprise login form $('.login-enterprise-button').trigger('click'); @@ -2403,7 +2403,7 @@ $('#enterpriseConfiguration').validator().on('submit', function(event) { setTimeout(checkGroupErrors, 0); }); -$('#unsignedConfiguration').validator().on('submit', function(event) { +$('#unsignedConfiguration').validator().on('submit', function (event) { if (event.isDefaultPrevented()) { // Gives time to Validator to apply classes setTimeout(checkGroupErrors, 0); @@ -2511,7 +2511,7 @@ $('.login-appStore-button').on('click', function () { $this.removeClass('disabled'); return appStoreTeamSetup(devEmail, true); }) - .catch(function(error) { + .catch(function (error) { var message = 'Unable to log in'; if (Fliplet.parseError(error)) { @@ -2633,7 +2633,7 @@ $('.appStore-generate-cert').on('click', function () { organizationId: organizationID, submissionId: appStoreSubmission.id }) - .then(function(response) { + .then(function (response) { var p12Url = Fliplet.Env.get('apiUrl') + 'v1/organizations/' + organizationID + '/credentials/submission-' + appStoreSubmission.id + '/download/p12' appStoreCertificateCreated = true; $('.appStore-generate-file-success').find('.appStore-file-name-success').html(response.certificate.name); @@ -2645,7 +2645,7 @@ $('.appStore-generate-cert').on('click', function () { $this.removeClass('disabled'); }); }) - .catch(function(error) { + .catch(function (error) { $this.html('Generate certificate'); $this.removeClass('disabled'); console.log(error); @@ -2683,7 +2683,7 @@ $('.appStore-replace-cert').on('click', function () { organizationId: organizationID, submissionId: appStoreSubmission.id }) - .then(function(response) { + .then(function (response) { var p12Url = Fliplet.Env.get('apiUrl') + 'v1/organizations/' + organizationID + '/credentials/submission-' + appStoreSubmission.id + '/download/p12' appStoreCertificateReplaced = true; $('.appStore-previous-file-success').find('.appStore-file-name-success').html(response.certificate.name); @@ -2695,7 +2695,7 @@ $('.appStore-replace-cert').on('click', function () { }); }); }) - .catch(function(error) { + .catch(function (error) { $this.html('Replace certificate'); $this.removeClass('disabled'); console.log(error); @@ -2755,7 +2755,7 @@ $('.login-enterprise-button').on('click', function () { $this.removeClass('disabled'); return enterpriseTeamSetup(devEmail, true); }) - .catch(function(error) { + .catch(function (error) { var message = 'Unable to log in'; if (Fliplet.parseError(error)) { @@ -2875,7 +2875,7 @@ $('.enterprise-generate-cert').on('click', function () { submissionId: enterpriseSubmission.id, inHouse: true }) - .then(function(response) { + .then(function (response) { var p12Url = Fliplet.Env.get('apiUrl') + 'v1/organizations/' + organizationID + '/credentials/submission-' + enterpriseSubmission.id + '/download/p12' enterpriseCertificateCreated = true; $('.enterprise-generate-file-success').find('.enterprise-file-name-success').html(response.certificate.name); @@ -2887,7 +2887,7 @@ $('.enterprise-generate-cert').on('click', function () { $this.removeClass('disabled'); }); }) - .catch(function(error) { + .catch(function (error) { $this.html('Generate certificate'); $this.removeClass('disabled'); console.log(error); @@ -2944,7 +2944,7 @@ $('.enterprise-replace-cert').on('click', function () { submissionId: enterpriseSubmission.id, inHouse: true }) - .then(function(response) { + .then(function (response) { var p12Url = Fliplet.Env.get('apiUrl') + 'v1/organizations/' + organizationID + '/credentials/submission-' + enterpriseSubmission.id + '/download/p12' enterpriseCertificateReplaced = true; $('.enterprise-previous-file-success').find('.enterprise-file-name-success').html(response.certificate.name); @@ -2956,7 +2956,7 @@ $('.enterprise-replace-cert').on('click', function () { }); }); }) - .catch(function(error) { + .catch(function (error) { $this.html('Replace certificate'); $this.removeClass('disabled'); console.log(error); @@ -3013,7 +3013,7 @@ $(document).on('click', '[data-cancel-build-id]', function () { }) }); -$('.browse-files').on('click', function(e) { +$('.browse-files').on('click', function (e) { e.preventDefault(); Fliplet.Studio.emit('overlay', { From 1a1061416b03f9e2e88128f518403ae4b740b14c Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Fri, 22 Feb 2019 16:27:05 +0000 Subject: [PATCH 121/318] Spacing --- js/interface.js | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/js/interface.js b/js/interface.js index f244051..0bc42ee 100644 --- a/js/interface.js +++ b/js/interface.js @@ -279,13 +279,14 @@ function clearAppStoreCredentials() { email: null, password: null, teamId: null - }, false).then(function () { - appStoreLoggedIn = false; - $('#fl-store-appDevPass').prop('required', true); - $('.appStore-logged-email').html(''); - $('.appStore-login-details').removeClass('hidden'); - $('.appStore-logged-in, .appStore-more-options, .appStore-teams').removeClass('show'); - }); + }, false) + .then(function () { + appStoreLoggedIn = false; + $('#fl-store-appDevPass').prop('required', true); + $('.appStore-logged-email').html(''); + $('.appStore-login-details').removeClass('hidden'); + $('.appStore-logged-in, .appStore-more-options, .appStore-teams').removeClass('show'); + }); } function loadAppStoreTeams(devEmail) { @@ -456,13 +457,14 @@ function clearEnterpriseCredentials() { email: null, password: null, teamId: null - }, false).then(function () { - enterpriseLoggedIn = false; - $('#fl-ent-appDevPass').prop('required', true); - $('.enterprise-logged-email').html(''); - $('.enterprise-login-details').removeClass('hidden'); - $('.enterprise-logged-in, .enterprise-more-options, .enterprise-teams').removeClass('show'); - }); + }, false) + .then(function () { + enterpriseLoggedIn = false; + $('#fl-ent-appDevPass').prop('required', true); + $('.enterprise-logged-email').html(''); + $('.enterprise-login-details').removeClass('hidden'); + $('.enterprise-logged-in, .enterprise-more-options, .enterprise-teams').removeClass('show'); + }); } function loadEnterpriseTeams(devEmail) { @@ -2506,10 +2508,12 @@ $('.login-appStore-button').on('click', function () { email: devEmail, password: devPass }) + .then(function () { + return appStoreTeamSetup(devEmail, true); + }) .then(function () { $this.html('Log in'); $this.removeClass('disabled'); - return appStoreTeamSetup(devEmail, true); }) .catch(function (error) { var message = 'Unable to log in'; @@ -2749,11 +2753,13 @@ $('.login-enterprise-button').on('click', function () { email: devEmail, password: devPass }) + .then(function () { + return enterpriseTeamSetup(devEmail, true); + }) .then(function () { $('[name="fl-ent-distribution"][value="generate-file"]').prop('checked', true).trigger('change'); $this.html('Log in'); $this.removeClass('disabled'); - return enterpriseTeamSetup(devEmail, true); }) .catch(function (error) { var message = 'Unable to log in'; From f687e2ff5abff2cee3257df29d85d7b4a4283373 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Fri, 22 Feb 2019 16:27:13 +0000 Subject: [PATCH 122/318] Prevents forms from submitting --- interface.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface.html b/interface.html index 9be287f..17b0bc3 100644 --- a/interface.html +++ b/interface.html @@ -599,7 +599,7 @@

    Apple developer account details and distribution certificates
    - + Load teams
    + + +
    @@ -952,7 +989,7 @@
    @@ -1018,7 +1055,7 @@

    Reviewer Notes

    -

    The phone number needs to include the area code. (Eg.: +44)

    +

    The phone number needs to include the area code. (e.g. +44)

    @@ -1192,6 +1229,43 @@

    Apple developer account details and distribution certificates + + +

    Warning! This area should only be used if you have technical knowledge on enterprise app submissions, p12 files and mobile provisioning files.

    diff --git a/js/interface.js b/js/interface.js index 9337830..4a1db8d 100644 --- a/js/interface.js +++ b/js/interface.js @@ -45,6 +45,7 @@ var spinner = ''; var socket = Fliplet.Socket({ login: true }); +var socketClientId; /* FUNCTIONS */ String.prototype.toCamelCase = function () { @@ -2017,76 +2018,36 @@ function initialLoad(initial, timeout) { } } -function select2FADevice(data) { - data = data || {}; - - var options = _.map(data.devices, function (value, index) { - return { - text: value, - value: index + 1 - }; - }); - - return Fliplet.Modal.prompt({ - title: 'Your Apple ID is protected with two-step verification. Choose a trusted device to receive a verification code.', - size: 'small', - inputType: 'select', - inputOptions: options - }).then(function (selection) { - if (selection === null) { - return null; - } - - if (selection === '') { - return Fliplet.Modal.alert({ - message: 'You must choose a device to continue.', - size: 'small' - }).then(function () { - return select2FADevice(data); - }); - } - - return selection; - }); -} - -function prompt2FA() { +function updateServerLocation() { var region = Fliplet.User.getAuthToken().substr(0, 2); var serverLocations = { eu: 'Dublin, Ireland', us: 'San Francisco, US' }; - return Fliplet.Modal.prompt({ - title: [ - 'Apple has sent a verification code to your devices from ', - serverLocations[region] - ? '' + serverLocations[region] + '' - : 'one of Fliplet\'s server locations', - '. Please enter the code to continue.
    Note: If you don\'t receive the code, please check your Apple account settings.
    ' - ].join(''), - size: 'small' - }).then(function (code) { - if (code === null) { - return null; - } - - if (code === '') { - return Fliplet.Modal.alert({ - message: 'You must enter the verification code to continue.', - size: 'small' - }).then(function () { - return prompt2FA(); - }); - } + if (serverLocations[region]) { + $('.region-server-location').html(serverLocations[region]); + } +} - return code; - }); +function getCurrentLoginForm() { + var id = $('.nav-tabs > li.active').prop('id'); + + if (!id) { + return; + } + + var ids = { + 'appstore-control': 'app-store', + 'enterprise-control': 'enterprise' + }; + + return ids[id]; } function toggleLoginForm(form, state, data) { // form @param (String) app-store | enterprise - // state @param (String) login | 2fa-device | 2fa-code | logged-in + // state @param (String) login | logging-in | 2fa-device | 2fa-waiting | 2fa-code | 2fa-verifying | 2fa-sms | logged-in // data @param (Object) Data for configuring forms (Optional) var selectors = { @@ -2094,6 +2055,14 @@ function toggleLoginForm(form, state, data) { emailField: '#fl-store-appDevLogin', passwordField: '#fl-store-appDevPass', loginButton: '.login-appStore-button', + mfaDevices: '.appStore-login-2fa-devices', + mfaDeviceField: '#fl-store-2fa-select', + mfaDeviceName: 'fl-store-device', + mfaCodeWaiting: '.appStore-login-2fa-waiting', + mfaCode: '.appStore-login-2fa-code', + mfaSms: '.appStore-2fa-sms', + mfaCodeField: '#fl-store-2fa-code', + mfaCodeButton: '.2fa-code-store-button', loginDetails: '.appStore-login-details', loggedInEmail: '.appStore-logged-email', loggedIn: '.appStore-logged-in', @@ -2104,6 +2073,14 @@ function toggleLoginForm(form, state, data) { emailField: '#fl-ent-appDevLogin', passwordField: '#fl-ent-appDevPass', loginButton: '.login-enterprise-button', + mfaDevices: '.enterprise-login-2fa-devices', + mfaDeviceField: '#fl-ent-2fa-select', + mfaDeviceName: 'fl-ent-device', + mfaCodeWaiting: '.enterprise-login-2fa-waiting', + mfaCode: '.enterprise-login-2fa-code', + mfaSms: '.enterprise-2fa-sms', + mfaCodeField: '#fl-ent-2fa-code', + mfaCodeButton: '.2fa-code-ent-button', loginDetails: '.enterprise-login-details', loggedInEmail: '.enterprise-logged-email', loggedIn: '.enterprise-logged-in', @@ -2126,29 +2103,68 @@ function toggleLoginForm(form, state, data) { readonly: false, required: true }); + $([sel.mfaDeviceField, sel.mfaCodeField].join(',')).prop('required', false); $(sel.loginButton).html('Log in').removeClass('disabled'); - $(sel.loggedInEmail).html(''); $(sel.loginDetails).removeClass('hidden'); - $([sel.loggedIn, sel.moreOptions, sel.teams].join(',')).removeClass('show'); + $([sel.mfaDevices, sel.mfaCode, sel.loggedIn, sel.moreOptions, sel.teams].join(',')).removeClass('show'); break; case 'logging-in': - $(sel.loginButton).html('Logging in ' + spinner).addClass('disabled'); $([sel.emailField, sel.passwordField].join(',')).prop({ readonly: true }); + $(sel.loginButton).html('Logging in ' + spinner).addClass('disabled'); + $(sel.loginDetails).removeClass('hidden'); + $([sel.mfaDevices, sel.mfaCode, sel.loggedIn, sel.moreOptions, sel.teams].join(',')).removeClass('show'); break; case '2fa-device': + var options = _.map(_.get(data, 'devices', []), function eachDevice(device, i) { + return [ + '', + '' + device, + '' + ].join(''); + }).join(''); + $([sel.emailField, sel.passwordField, sel.mfaCodeField].join(',')).prop({ + required: false + }); + $(sel.mfaDeviceField).html(options).find('input').prop('required', true); + $([sel.emailField, sel.passwordField, sel.mfaCodeField].join(',')).prop('required', false); + $(sel.mfaDevices).addClass('show'); + $(sel.loginDetails).addClass('hidden'); + $([sel.mfaCode, sel.loggedIn, sel.moreOptions, sel.teams].join(',')).removeClass('show'); + break; + case '2fa-waiting': + $(sel.mfaCodeWaiting).addClass('show'); + $([sel.mfaDeviceField, sel.mfaCodeField].join(',')).prop('required', false); + $([sel.mfaCode, sel.mfaDevices, sel.mfaSms].join(',')).removeClass('show'); break; case '2fa-code': + $(sel.mfaCode).addClass('show'); + $(sel.mfaCodeField).val('').prop({ + required: true, + readonly: false + }).focus(); + $(sel.mfaCodeButton).html('Verify').prop('disabled', false); + $([sel.emailField, sel.passwordField, sel.mfaDeviceField].join(',')).prop('required', false); + $(sel.loginDetails).addClass('hidden'); + $([sel.mfaDevices, sel.mfaSms, sel.mfaCodeWaiting, sel.loggedIn, sel.moreOptions, sel.teams].join(',')).removeClass('show'); + break; + case '2fa-sms': + $(sel.mfaSms).addClass('show'); + break; + case '2fa-verifying': + $(sel.mfaCodeField).prop('readonly', true); + $(sel.mfaCodeButton).html('Verifying ' + spinner).prop('disabled', true); break; case 'logged-in': - $([sel.emailField, sel.passwordField].join(',')).prop({ + $([sel.emailField, sel.passwordField, sel.mfaDeviceField, sel.mfaCodeField].join(',')).prop({ required: false }); $(sel.emailField).val(data.email); $(sel.loggedInEmail).html(data.email); $(sel.loginDetails).addClass('hidden'); $([sel.loggedIn, sel.teams].join(',')).addClass('show'); + $([sel.mfaDevices, sel.mfaCode].join(',')).removeClass('show'); break; } @@ -2156,6 +2172,28 @@ function toggleLoginForm(form, state, data) { } /* ATTACH LISTENERS */ + +$('[data-toggle="tooltip"]').tooltip(); + +$('.appStore-2fa-sms, .enterprise-2fa-sms').find('a').on('click', function (e) { + e.preventDefault(); + // Send SMS request via socket + toggleLoginForm(getCurrentLoginForm(), '2fa-waiting'); + socket.to(socketClientId).emit('aab.apple.login.2fa.sms'); +}); + +$('#fl-store-2fa-select, #fl-ent-2fa-select').on('change', function (e) { + // Send device selection via socket + toggleLoginForm(getCurrentLoginForm(), '2fa-waiting'); + socket.to(socketClientId).emit('aab.apple.login.2fa.device', e.target.value); +}); + +$('.2fa-code-store-button, .2fa-code-ent-button').on('click', function (e) { + var code = $(this).parents('.form-group').prev().find('.form-control').val(); + toggleLoginForm(getCurrentLoginForm(), '2fa-verifying'); + socket.to(socketClientId).emit('aab.apple.login.2fa.code', code); +}); + $('[name="fl-store-screenshots"]').on('change', function () { var value = $(this).val(); var id = $(this).attr('id'); @@ -2240,6 +2278,7 @@ $('.panel-group') $('a[data-toggle="tab"]') .on('shown.bs.tab', function () { Fliplet.Widget.autosize(); + socket.to(socketClientId).emit('aab.apple.login.2fa.cancel'); }) .on('hidden.bs.tab', function () { Fliplet.Widget.autosize(); @@ -2303,6 +2342,12 @@ $('#appStoreConfiguration').validator().on('submit', function (event) { return; } + if (document.activeElement.id === 'fl-store-2fa-code') { + // User submitted app store login form + $('.2fa-code-store-button').trigger('click'); + return; + } + if (event.isDefaultPrevented()) { // Gives time to Validator to apply classes setTimeout(checkGroupErrors, 0); @@ -2391,6 +2436,12 @@ $('#enterpriseConfiguration').validator().on('submit', function (event) { return; } + if (document.activeElement.id === 'fl-ent-2fa-code') { + // User submitted app store login form + $('.2fa-code-ent-button').trigger('click'); + return; + } + if (event.isDefaultPrevented()) { // Gives time to Validator to apply classes setTimeout(checkGroupErrors, 0); @@ -3078,38 +3129,31 @@ $('.browse-files').on('click', function (e) { }); }); -/* INIT */ -$('#appStoreConfiguration, #enterpriseConfiguration, #unsignedConfiguration').validator().off('change.bs.validator focusout.bs.validator'); -$('[name="submissionType"][value="appStore"]').prop('checked', true).trigger('change'); - -// Start -initLoad = initialLoad(true, 0); - // Listen for 2FA code when requested socket.on('aab.apple.login.2fa', function (data) { + socketClientId = data.clientId; // Ask user for code - prompt2FA().then(function (code) { - if (code === null) { - socket.to(data.clientId).emit('aab.apple.login.2fa.cancel'); - return; - } - - socket.to(data.clientId).emit('aab.apple.login.2fa.code', code); - }).catch(function () { - socket.to(data.clientId).emit('aab.apple.login.2fa.cancel'); - }); + toggleLoginForm(getCurrentLoginForm(), '2fa-code'); }); socket.on('aab.apple.login.2fa.devices', function (data) { - // Ask user to select device - select2FADevice(data).then(function (selection) { - if (selection === null) { - socket.to(data.clientId).emit('aab.apple.login.2fa.cancel'); - return; - } + socketClientId = data.clientId; + // Ask user for device + toggleLoginForm(getCurrentLoginForm(), '2fa-device', data); +}); - socket.to(data.clientId).emit('aab.apple.login.2fa.device', selection); - }).catch(function () { - socket.to(data.clientId).emit('aab.apple.login.2fa.cancel'); - }); +socket.on('aab.apple.login.2fa.sms.allowed', function () { + // Add SMS option + setTimeout(function () { + toggleLoginForm(getCurrentLoginForm(), '2fa-sms'); + }, 2000); }); + +/* INIT */ +$('#appStoreConfiguration, #enterpriseConfiguration, #unsignedConfiguration').validator().off('change.bs.validator focusout.bs.validator'); +$('[name="submissionType"][value="appStore"]').prop('checked', true).trigger('change'); + +updateServerLocation(); + +// Start +initLoad = initialLoad(true, 0); \ No newline at end of file From fc580a0cd153319d65128e2f9d486dd745351356 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Tue, 5 Mar 2019 08:13:05 +0000 Subject: [PATCH 139/318] Ensures 2FA code is entered --- js/interface.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/js/interface.js b/js/interface.js index 4a1db8d..65a3062 100644 --- a/js/interface.js +++ b/js/interface.js @@ -2190,6 +2190,14 @@ $('#fl-store-2fa-select, #fl-ent-2fa-select').on('change', function (e) { $('.2fa-code-store-button, .2fa-code-ent-button').on('click', function (e) { var code = $(this).parents('.form-group').prev().find('.form-control').val(); + + if (!code) { + Fliplet.Modal.alert({ + message: 'You must enter the verification code to continue' + }); + return; + } + toggleLoginForm(getCurrentLoginForm(), '2fa-verifying'); socket.to(socketClientId).emit('aab.apple.login.2fa.code', code); }); From 40c4f0580d66ff66b152cc915340f2f5d6aaa554 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Tue, 5 Mar 2019 10:05:29 +0000 Subject: [PATCH 140/318] Handle 2FA code request that support SMS fallback --- js/interface.js | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/js/interface.js b/js/interface.js index 65a3062..649b6b6 100644 --- a/js/interface.js +++ b/js/interface.js @@ -2047,7 +2047,7 @@ function getCurrentLoginForm() { function toggleLoginForm(form, state, data) { // form @param (String) app-store | enterprise - // state @param (String) login | logging-in | 2fa-device | 2fa-waiting | 2fa-code | 2fa-verifying | 2fa-sms | logged-in + // state @param (String) login | logging-in | 2fa-device | 2fa-waiting | 2fa-code | 2fa-verifying | logged-in // data @param (Object) Data for configuring forms (Optional) var selectors = { @@ -2144,13 +2144,12 @@ function toggleLoginForm(form, state, data) { required: true, readonly: false }).focus(); + // Show SMS option if allowed + $(sel.mfaSms)[data.smsAllowed ? 'addClass' : 'removeClass']('show'); $(sel.mfaCodeButton).html('Verify').prop('disabled', false); $([sel.emailField, sel.passwordField, sel.mfaDeviceField].join(',')).prop('required', false); $(sel.loginDetails).addClass('hidden'); - $([sel.mfaDevices, sel.mfaSms, sel.mfaCodeWaiting, sel.loggedIn, sel.moreOptions, sel.teams].join(',')).removeClass('show'); - break; - case '2fa-sms': - $(sel.mfaSms).addClass('show'); + $([sel.mfaDevices, sel.mfaCodeWaiting, sel.loggedIn, sel.moreOptions, sel.teams].join(',')).removeClass('show'); break; case '2fa-verifying': $(sel.mfaCodeField).prop('readonly', true); @@ -3141,7 +3140,7 @@ $('.browse-files').on('click', function (e) { socket.on('aab.apple.login.2fa', function (data) { socketClientId = data.clientId; // Ask user for code - toggleLoginForm(getCurrentLoginForm(), '2fa-code'); + toggleLoginForm(getCurrentLoginForm(), '2fa-code', data); }); socket.on('aab.apple.login.2fa.devices', function (data) { @@ -3150,13 +3149,6 @@ socket.on('aab.apple.login.2fa.devices', function (data) { toggleLoginForm(getCurrentLoginForm(), '2fa-device', data); }); -socket.on('aab.apple.login.2fa.sms.allowed', function () { - // Add SMS option - setTimeout(function () { - toggleLoginForm(getCurrentLoginForm(), '2fa-sms'); - }, 2000); -}); - /* INIT */ $('#appStoreConfiguration, #enterpriseConfiguration, #unsignedConfiguration').validator().off('change.bs.validator focusout.bs.validator'); $('[name="submissionType"][value="appStore"]').prop('checked', true).trigger('change'); From dc49e586f1ba693958a069d51c9611f83b07d8ea Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Tue, 5 Mar 2019 14:15:41 +0000 Subject: [PATCH 141/318] Don't send socket messages unless there's a client ID --- js/interface.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/js/interface.js b/js/interface.js index 649b6b6..91b8222 100644 --- a/js/interface.js +++ b/js/interface.js @@ -2285,7 +2285,10 @@ $('.panel-group') $('a[data-toggle="tab"]') .on('shown.bs.tab', function () { Fliplet.Widget.autosize(); - socket.to(socketClientId).emit('aab.apple.login.2fa.cancel'); + + if (socketClientId) { + socket.to(socketClientId).emit('aab.apple.login.2fa.cancel'); + } }) .on('hidden.bs.tab', function () { Fliplet.Widget.autosize(); From 22c6226f22fdcc690da38968a85a12847d5b1d54 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Tue, 5 Mar 2019 15:52:05 +0000 Subject: [PATCH 142/318] Updates selector mechanism --- js/interface.js | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/js/interface.js b/js/interface.js index 91b8222..06a3f69 100644 --- a/js/interface.js +++ b/js/interface.js @@ -2045,6 +2045,18 @@ function getCurrentLoginForm() { return ids[id]; } +function getSelectors(selectors, keys) { + selectors = selectors || {}; + + if (typeof keys === 'string') { + keys = [keys]; + } + + keys = keys || []; + + return _.values(_.pick(selectors, keys)).join(','); +} + function toggleLoginForm(form, state, data) { // form @param (String) app-store | enterprise // state @param (String) login | logging-in | 2fa-device | 2fa-waiting | 2fa-code | 2fa-verifying | logged-in @@ -2099,22 +2111,22 @@ function toggleLoginForm(form, state, data) { switch (state) { case 'login': - $([sel.emailField, sel.passwordField].join(',')).prop({ + $(getSelectors(sel, ['emailField', 'passwordField'])).prop({ readonly: false, required: true }); - $([sel.mfaDeviceField, sel.mfaCodeField].join(',')).prop('required', false); + $(getSelectors(sel, ['mfaDeviceField', 'mfaCodeField'])).prop('required', false); $(sel.loginButton).html('Log in').removeClass('disabled'); $(sel.loginDetails).removeClass('hidden'); - $([sel.mfaDevices, sel.mfaCode, sel.loggedIn, sel.moreOptions, sel.teams].join(',')).removeClass('show'); + $(getSelectors(sel, ['mfaDevices', 'mfaCode', 'loggedIn', 'moreOptions', 'teams'])).removeClass('show'); break; case 'logging-in': - $([sel.emailField, sel.passwordField].join(',')).prop({ + $(getSelectors(['emailField', 'passwordField'])).prop({ readonly: true }); $(sel.loginButton).html('Logging in ' + spinner).addClass('disabled'); $(sel.loginDetails).removeClass('hidden'); - $([sel.mfaDevices, sel.mfaCode, sel.loggedIn, sel.moreOptions, sel.teams].join(',')).removeClass('show'); + $(getSelectors(sel, ['mfaDevices', 'mfaCode', 'loggedIn', 'moreOptions', 'teams'])).removeClass('show'); break; case '2fa-device': var options = _.map(_.get(data, 'devices', []), function eachDevice(device, i) { @@ -2124,19 +2136,19 @@ function toggleLoginForm(form, state, data) { '' ].join(''); }).join(''); - $([sel.emailField, sel.passwordField, sel.mfaCodeField].join(',')).prop({ + $(getSelectors(sel, ['emailField', 'passwordField', 'mfaCodeField'])).prop({ required: false }); $(sel.mfaDeviceField).html(options).find('input').prop('required', true); - $([sel.emailField, sel.passwordField, sel.mfaCodeField].join(',')).prop('required', false); + $(getSelectors(sel, ['emailField', 'passwordField', 'mfaCodeField'])).prop('required', false); $(sel.mfaDevices).addClass('show'); $(sel.loginDetails).addClass('hidden'); - $([sel.mfaCode, sel.loggedIn, sel.moreOptions, sel.teams].join(',')).removeClass('show'); + $(getSelectors(sel, ['mfaCodeWaiting', 'mfaCode', 'loggedIn', 'moreOptions', 'teams'])).removeClass('show'); break; case '2fa-waiting': $(sel.mfaCodeWaiting).addClass('show'); - $([sel.mfaDeviceField, sel.mfaCodeField].join(',')).prop('required', false); - $([sel.mfaCode, sel.mfaDevices, sel.mfaSms].join(',')).removeClass('show'); + $(getSelectors(sel, ['mfaDeviceField', 'mfaCodeField'])).prop('required', false); + $(getSelectors(sel, ['mfaCode', 'mfaDevices', 'mfaSms'])).removeClass('show'); break; case '2fa-code': $(sel.mfaCode).addClass('show'); @@ -2147,23 +2159,23 @@ function toggleLoginForm(form, state, data) { // Show SMS option if allowed $(sel.mfaSms)[data.smsAllowed ? 'addClass' : 'removeClass']('show'); $(sel.mfaCodeButton).html('Verify').prop('disabled', false); - $([sel.emailField, sel.passwordField, sel.mfaDeviceField].join(',')).prop('required', false); + $(getSelectors(sel, 'emailField, passwordField, mfaDeviceField')).prop('required', false); $(sel.loginDetails).addClass('hidden'); - $([sel.mfaDevices, sel.mfaCodeWaiting, sel.loggedIn, sel.moreOptions, sel.teams].join(',')).removeClass('show'); + $(getSelectors(sel, ['mfaDevices', 'mfaCodeWaiting', 'loggedIn', 'moreOptions', 'teams'])).removeClass('show'); break; case '2fa-verifying': $(sel.mfaCodeField).prop('readonly', true); $(sel.mfaCodeButton).html('Verifying ' + spinner).prop('disabled', true); break; case 'logged-in': - $([sel.emailField, sel.passwordField, sel.mfaDeviceField, sel.mfaCodeField].join(',')).prop({ + $(getSelectors(sel, ['emailField', 'passwordField', 'mfaDeviceField', 'mfaCodeField'])).prop({ required: false }); $(sel.emailField).val(data.email); $(sel.loggedInEmail).html(data.email); $(sel.loginDetails).addClass('hidden'); - $([sel.loggedIn, sel.teams].join(',')).addClass('show'); - $([sel.mfaDevices, sel.mfaCode].join(',')).removeClass('show'); + $(getSelectors(sel, ['loggedIn', 'teams'])).addClass('show'); + $(getSelectors(sel, ['mfaDevices', 'mfaCode'])).removeClass('show'); break; } From 1e7b3d617c89e9f4598a65aa952dfc957f2c78f6 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Tue, 5 Mar 2019 15:55:20 +0000 Subject: [PATCH 143/318] Function rename --- js/interface.js | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/js/interface.js b/js/interface.js index 06a3f69..7602c31 100644 --- a/js/interface.js +++ b/js/interface.js @@ -2045,7 +2045,7 @@ function getCurrentLoginForm() { return ids[id]; } -function getSelectors(selectors, keys) { +function mapSelectors(selectors, keys) { selectors = selectors || {}; if (typeof keys === 'string') { @@ -2111,22 +2111,22 @@ function toggleLoginForm(form, state, data) { switch (state) { case 'login': - $(getSelectors(sel, ['emailField', 'passwordField'])).prop({ + $(mapSelectors(sel, ['emailField', 'passwordField'])).prop({ readonly: false, required: true }); - $(getSelectors(sel, ['mfaDeviceField', 'mfaCodeField'])).prop('required', false); + $(mapSelectors(sel, ['mfaDeviceField', 'mfaCodeField'])).prop('required', false); $(sel.loginButton).html('Log in').removeClass('disabled'); $(sel.loginDetails).removeClass('hidden'); - $(getSelectors(sel, ['mfaDevices', 'mfaCode', 'loggedIn', 'moreOptions', 'teams'])).removeClass('show'); + $(mapSelectors(sel, ['mfaDevices', 'mfaCode', 'loggedIn', 'moreOptions', 'teams'])).removeClass('show'); break; case 'logging-in': - $(getSelectors(['emailField', 'passwordField'])).prop({ + $(mapSelectors(['emailField', 'passwordField'])).prop({ readonly: true }); $(sel.loginButton).html('Logging in ' + spinner).addClass('disabled'); $(sel.loginDetails).removeClass('hidden'); - $(getSelectors(sel, ['mfaDevices', 'mfaCode', 'loggedIn', 'moreOptions', 'teams'])).removeClass('show'); + $(mapSelectors(sel, ['mfaDevices', 'mfaCode', 'loggedIn', 'moreOptions', 'teams'])).removeClass('show'); break; case '2fa-device': var options = _.map(_.get(data, 'devices', []), function eachDevice(device, i) { @@ -2136,19 +2136,19 @@ function toggleLoginForm(form, state, data) { '' ].join(''); }).join(''); - $(getSelectors(sel, ['emailField', 'passwordField', 'mfaCodeField'])).prop({ + $(mapSelectors(sel, ['emailField', 'passwordField', 'mfaCodeField'])).prop({ required: false }); $(sel.mfaDeviceField).html(options).find('input').prop('required', true); - $(getSelectors(sel, ['emailField', 'passwordField', 'mfaCodeField'])).prop('required', false); + $(mapSelectors(sel, ['emailField', 'passwordField', 'mfaCodeField'])).prop('required', false); $(sel.mfaDevices).addClass('show'); $(sel.loginDetails).addClass('hidden'); - $(getSelectors(sel, ['mfaCodeWaiting', 'mfaCode', 'loggedIn', 'moreOptions', 'teams'])).removeClass('show'); + $(mapSelectors(sel, ['mfaCodeWaiting', 'mfaCode', 'loggedIn', 'moreOptions', 'teams'])).removeClass('show'); break; case '2fa-waiting': $(sel.mfaCodeWaiting).addClass('show'); - $(getSelectors(sel, ['mfaDeviceField', 'mfaCodeField'])).prop('required', false); - $(getSelectors(sel, ['mfaCode', 'mfaDevices', 'mfaSms'])).removeClass('show'); + $(mapSelectors(sel, ['mfaDeviceField', 'mfaCodeField'])).prop('required', false); + $(mapSelectors(sel, ['mfaCode', 'mfaDevices', 'mfaSms'])).removeClass('show'); break; case '2fa-code': $(sel.mfaCode).addClass('show'); @@ -2159,23 +2159,23 @@ function toggleLoginForm(form, state, data) { // Show SMS option if allowed $(sel.mfaSms)[data.smsAllowed ? 'addClass' : 'removeClass']('show'); $(sel.mfaCodeButton).html('Verify').prop('disabled', false); - $(getSelectors(sel, 'emailField, passwordField, mfaDeviceField')).prop('required', false); + $(mapSelectors(sel, 'emailField, passwordField, mfaDeviceField')).prop('required', false); $(sel.loginDetails).addClass('hidden'); - $(getSelectors(sel, ['mfaDevices', 'mfaCodeWaiting', 'loggedIn', 'moreOptions', 'teams'])).removeClass('show'); + $(mapSelectors(sel, ['mfaDevices', 'mfaCodeWaiting', 'loggedIn', 'moreOptions', 'teams'])).removeClass('show'); break; case '2fa-verifying': $(sel.mfaCodeField).prop('readonly', true); $(sel.mfaCodeButton).html('Verifying ' + spinner).prop('disabled', true); break; case 'logged-in': - $(getSelectors(sel, ['emailField', 'passwordField', 'mfaDeviceField', 'mfaCodeField'])).prop({ + $(mapSelectors(sel, ['emailField', 'passwordField', 'mfaDeviceField', 'mfaCodeField'])).prop({ required: false }); $(sel.emailField).val(data.email); $(sel.loggedInEmail).html(data.email); $(sel.loginDetails).addClass('hidden'); - $(getSelectors(sel, ['loggedIn', 'teams'])).addClass('show'); - $(getSelectors(sel, ['mfaDevices', 'mfaCode'])).removeClass('show'); + $(mapSelectors(sel, ['loggedIn', 'teams'])).addClass('show'); + $(mapSelectors(sel, ['mfaDevices', 'mfaCode'])).removeClass('show'); break; } From b0d202189efc253e62f20c899f84573604f6d032 Mon Sep 17 00:00:00 2001 From: Nicholas Valbusa Date: Wed, 6 Mar 2019 11:45:56 +0100 Subject: [PATCH 144/318] fixes for setting an app password on app store credentials not needing to be verified --- js/interface.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/interface.js b/js/interface.js index aa5e815..92ad2a7 100644 --- a/js/interface.js +++ b/js/interface.js @@ -808,7 +808,7 @@ function requestBuild(origin, submission) { setCredentials(appStoreSubmission.id, { appPassword: $('#fl-store-appPassword').val().trim() - }).then(function () { + }, false).then(function () { return Fliplet.App.Submissions.update(submission.id, submission.data); }).then(function () { // Check which type of certificate was given From 2eb2cb93cf56d22d73fff52ae7dd7e5717597461 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Mon, 25 Mar 2019 18:37:00 +0000 Subject: [PATCH 145/318] Adds support for new screenshot size requirements --- css/interface.css | 26 ++-- interface.html | 28 ++-- js/interface.js | 152 ++++++++++++-------- js/interface.templates.js | 35 ++++- js/templates/no-thumb.interface.hbs | 3 + js/templates/thumb-containers.interface.hbs | 6 + js/templates/thumbs.interface.hbs | 2 +- 7 files changed, 160 insertions(+), 92 deletions(-) create mode 100644 js/templates/no-thumb.interface.hbs create mode 100644 js/templates/thumb-containers.interface.hbs diff --git a/css/interface.css b/css/interface.css index fc50214..aff4a90 100644 --- a/css/interface.css +++ b/css/interface.css @@ -119,6 +119,10 @@ border-color: #a94442; } +.panel-default.required-fill + .panel-default:not(.required-fill) { + margin-top: 0; +} + .app-details-error, .app-details-warning { display: none; @@ -476,26 +480,18 @@ h3 small { margin-top: 10px; } -.hidden-area { - display: none; - background-color: #f2f6f7; - border-radius: 6px; - padding: 15px 15px 1px 15px; +.alert-inset { margin-top: 10px; margin-bottom: 20px; margin-left: 25px; } -.hidden-area.warning { - color: #8a6d3b; - background-color: #fcf8e3; - border: 1px solid #faebcc; +.alert > p, .alert > ul { + margin-bottom: 10px; } -.hidden-area.danger { - color: #a94442; - background-color: #f2dede; - border-color: #ebccd1; +.alert > p:fist-child:last-child, .alert > ul:fist-child:last-child { + margin-bottom: 0; } .radio.radio-icon ~ .radio.radio-icon, @@ -520,4 +516,8 @@ h3 small { .screenshot-previews img { border: 1px solid #F0F0F0; +} + +.screenshot-previews .alert { + margin-bottom: 0; } \ No newline at end of file diff --git a/interface.html b/interface.html index 866c6bd..91743c0 100644 --- a/interface.html +++ b/interface.html @@ -84,23 +84,13 @@
    -
    -

    Apple requires you to upload up to 4 screenshots of your app for mobile and tablet devices. We could not find any screenshots in your folders, please go to App Settings to generate your screenshots.

    + -
    -

    We will use the following screenshot in your app listing in the order shown below.
    - We order the screenshots alphabetically, to reorder go to File Manager and rename your screenshots.

    - -
    -
    Mobile
    -
    -
    -
    -
    Tablet
    -
    -
    - -

    If you want to generate or upload new screenshots go to App Settings.

    + +
    @@ -110,9 +100,9 @@
    -
    -

    We will not upload new screenshots, we will use the existing screenshots on the app listing. By selecting this option you are confirming that you already have an app listing on the Apple App Store and that it contains the screenshots you want to be publicaly available.

    -

    The app submission will fail if the app listing doesn’t contain screenshots.

    +
    diff --git a/js/interface.js b/js/interface.js index 92ad2a7..3637661 100644 --- a/js/interface.js +++ b/js/interface.js @@ -36,9 +36,28 @@ var initLoad; var organizationID = Fliplet.Env.get('organizationId'); var userInfo; var hasFolders = false; -var screenShotsMobile = []; -var screenShotsTablet = []; -var haveScreenshots = false; +// Each collection requirement will need to match at least one of the width/height sizes +var screenshotRequirements = [ + { + type: 'mobile', + name: 'iPhone 5.5-inch Display', + sizes: [[1242, 2208]], + screenshots: [] + }, + { + type: 'mobilex', + name: 'iPhone 6.5-inch Display', + sizes: [[1242, 2688]], + screenshots: [] + }, + { + type: 'tablet', + name: 'iPad Pro 12.9-inch Display', + sizes: [[2048, 2732], [2732, 2048]], + screenshots: [] + } +]; +var hasAllScreenshots = false; var screenshotValidationNotRequired = false; var spinner = ''; @@ -76,8 +95,11 @@ function incrementVersionNumber(versionNumber) { return splitNumber.join('.'); } -function checkHasScreenshots() { - haveScreenshots = hasFolders && screenShotsMobile.length && screenShotsTablet.length; +function checkHasAllScreenshots() { + hasAllScreenshots = hasFolders && _.every(screenshotRequirements, function (req) { + return req.screenshots.length; + }); + return hasAllScreenshots; } function addThumb(thumb) { @@ -85,7 +107,18 @@ function addThumb(thumb) { return template(thumb); } +function addNoScreenshotWarning(req) { + var template = Fliplet.Widget.Templates['templates.no-thumb']; + return template(req); +} + +function addScreenshotThumbContainers() { + var template = Fliplet.Widget.Templates['templates.thumb-containers']; + $('.screenshot-thumb-containers').html(template(screenshotRequirements)); +} + function loadAppStoreData() { + addScreenshotThumbContainers(); $('#appStoreConfiguration [name]').each(function (i, el) { var name = $(el).attr("name"); @@ -208,7 +241,7 @@ function loadAppStoreData() { $('[name="' + name + '"]').val((typeof appStoreSubmission.data[name] !== "undefined") ? appStoreSubmission.data[name] : ''); }); - if (appName !== '' && appIcon && ((hasFolders && screenShotsMobile.length && screenShotsTablet.length) || screenshotValidationNotRequired)) { + if (appName !== '' && appIcon && (checkHasAllScreenshots() || screenshotValidationNotRequired)) { if (appSettings.splashScreen && appSettings.splashScreen.size && (appSettings.splashScreen.size[0] && appSettings.splashScreen.size[1]) < 2732) { $('.app-details-appStore .app-splash-screen').addClass('has-warning'); } @@ -228,10 +261,9 @@ function loadAppStoreData() { } if ($('[name="fl-store-screenshots"]:checked').val() === 'new' - && (!hasFolders - || !screenShotsMobile.length - || !screenShotsTablet.length - ) + && (!hasFolders || _.some(screenshotRequirements, function (req) { + return !req.screenshots.length; + })) ) { $('.app-details-appStore .app-screenshots').addClass('has-error'); } @@ -1533,25 +1565,34 @@ function checkGroupErrors() { function validateScreenshots() { var imageErrors = []; - var supportedFormats = [[1242,2208], [2048,2732], [2732,2048]]; - var allScreenShots = _.concat(screenShotsMobile, screenShotsTablet); - - _.forEach(allScreenShots, function (screenshot, key) { - var supportedSize = _.find(supportedFormats, function (format) { - return format[0] === screenshot.size[0] && format[1] === screenshot.size[1]; + var supportedFormats = _.uniqBy(_.concat.apply(null, _.map(screenshotRequirements, 'sizes')), + function (req) { + return req[0] + ' x ' + req[1]; }); - if (!screenshot.appId && !supportedSize) { + _.forEach(screenshotRequirements, function (req) { + _.forEach(req.screenshots, function (screenshot) { + var supportedSize = _.some(req.sizes, function (size) { + return size[0] === screenshot.size[0] && size[1] === screenshot.size[1]; + }); + + if (screenshot.appId && supportedSize) { + return; + } + imageErrors.push(screenshot.name + ' - ' + screenshot.size[0] + ' x ' + screenshot.size[1]); - } + }); }); if (imageErrors.length > 0) { - imageErrors.unshift('The following screenshots have an invalid size:'); imageErrors.push('Supported screenshot sizes are:'); - imageErrors.push('1242 x 2208 | 2048 x 2732 | 2732 x 2048'); - var errorMessage = _.join(imageErrors, '\n\r'); - alert(errorMessage); + imageErrors.push(_.map(supportedFormats, function (format) { + return format[0] + ' × ' + format[1]; + }).join(' | ')); + Fliplet.Modal.alert({ + title: 'The following screenshots have an invalid size', + message: _.join(imageErrors, '
    ') + }); return false; } @@ -1985,12 +2026,13 @@ function initialLoad(initial, timeout) { }); })) .then(function () { - structure.forEach(function (el, idx) { - if (el.type === 'mobile') { - screenShotsMobile = el.folderContent.files - } - if (el.type === 'tablet') { - screenShotsTablet = el.folderContent.files + structure.forEach(function (el) { + var idx = _.findIndex(screenshotRequirements, { + type: el.type + }); + + if (idx > -1) { + screenshotRequirements[idx].screenshots = el.folderContent.files; } }); }); @@ -2214,39 +2256,33 @@ $('.2fa-code-store-button, .2fa-code-ent-button').on('click', function (e) { }); $('[name="fl-store-screenshots"]').on('change', function () { - var value = $(this).val(); var id = $(this).attr('id'); - checkHasScreenshots(); - - if (value === 'new' && !haveScreenshots) { - $('[data-item="fl-store-screenshots-new-warning"]').addClass('show'); - - $('[data-item="fl-store-screenshots-new"]').removeClass('show'); - $('[data-item="fl-store-screenshots-existing"]').removeClass('show'); - } - - if (value === 'new' && haveScreenshots) { - $('[data-item="fl-store-screenshots-new-warning"]').removeClass('show'); - $('[data-item="fl-store-screenshots-new"]').addClass('show'); - $('[data-item="fl-store-screenshots-existing"]').removeClass('show'); + switch ($(this).val()) { + case 'new': + _.forEach(screenshotRequirements, function (req) { + var $thumbContainer = $('.thumbs[data-type="' + req.type + '"]'); + $thumbContainer.html(''); + if (!req.screenshots.length) { + $thumbContainer.append(addNoScreenshotWarning(req)); + return; + } - _.take(screenShotsMobile, 4).forEach(function (thumb) { - $('.mobile-thumbs').append(addThumb(thumb)); - }); - - _.take(screenShotsTablet, 4).forEach(function (thumb) { - $('.tablet-thumbs').append(addThumb(thumb)); - }); - } - - if (value === 'existing') { - $('.app-details-appStore .app-screenshots').removeClass('has-error'); - $('[data-item="fl-store-screenshots-existing"]').addClass('show'); + _.forEach(_.take(req.screenshots, 4), function (thumb) { + $thumbContainer.append(addThumb(thumb)); + }); + }); - $('[data-item="fl-store-screenshots-new-warning"]').removeClass('show'); - $('[data-item="fl-store-screenshots-new"]').removeClass('show'); + $('[data-item="fl-store-screenshots-new"]').removeClass('hidden'); + $('[data-item="fl-store-screenshots-existing"]').addClass('hidden'); + break; + case 'existing': + $('.app-details-appStore .app-screenshots').removeClass('has-error'); + $('[data-item="fl-store-screenshots-existing"]').removeClass('hidden'); + $('[data-item="fl-store-screenshots-new-warning"]').addClass('hidden'); + $('[data-item="fl-store-screenshots-new"]').addClass('hidden'); + break; } }); @@ -2334,7 +2370,7 @@ $('.redirectToSettings, [data-change-settings]').on('click', function (event) { }); }); -$('[data-change-assets]').on('click', function (event) { +$(document).on('click', '[data-change-assets]', function (event) { event.preventDefault(); Fliplet.Studio.emit('close-overlay', { @@ -2381,7 +2417,7 @@ $('#appStoreConfiguration').validator().on('submit', function (event) { event.preventDefault(); - if ($('[name="fl-store-screenshots"]:checked').val() === 'new' && !haveScreenshots) { + if ($('[name="fl-store-screenshots"]:checked').val() === 'new' && !hasAllScreenshots) { Fliplet.Modal.alert({ message: 'You need to add screenshots before submitting' }); diff --git a/js/interface.templates.js b/js/interface.templates.js index 059f4f5..f464300 100644 --- a/js/interface.templates.js +++ b/js/interface.templates.js @@ -2,10 +2,43 @@ this["Fliplet"] = this["Fliplet"] || {}; this["Fliplet"]["Widget"] = this["Fliplet"]["Widget"] || {}; this["Fliplet"]["Widget"]["Templates"] = this["Fliplet"]["Widget"]["Templates"] || {}; +this["Fliplet"]["Widget"]["Templates"]["templates.no-thumb"] = Handlebars.template({"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { + var helper; + + return "
    \n
    Apple requires you to upload up to 4 screenshots of your app for " + + container.escapeExpression(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"name","hash":{},"data":data}) : helper))) + + ". To generate your screenshots, go to App Settings.
    \n
    "; +},"useData":true}); + +this["Fliplet"]["Widget"]["Templates"]["templates.thumb-containers"] = Handlebars.template({"1":function(container,depth0,helpers,partials,data) { + var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; + + return "
    \n

    " + + alias4(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"name","hash":{},"data":data}) : helper))) + + "
    " + + ((stack1 = helpers.each.call(alias1,(depth0 != null ? depth0.sizes : depth0),{"name":"each","hash":{},"fn":container.program(2, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + "

    \n
    \n
    \n"; +},"2":function(container,depth0,helpers,partials,data) { + var stack1, alias1=container.lambda, alias2=container.escapeExpression; + + return ((stack1 = helpers.unless.call(depth0 != null ? depth0 : (container.nullContext || {}),(data && data.first),{"name":"unless","hash":{},"fn":container.program(3, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + alias2(alias1((depth0 != null ? depth0["0"] : depth0), depth0)) + + " × " + + alias2(alias1((depth0 != null ? depth0["1"] : depth0), depth0)); +},"3":function(container,depth0,helpers,partials,data) { + return " or "; +},"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { + var stack1; + + return ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),depth0,{"name":"each","hash":{},"fn":container.program(1, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : ""); +},"useData":true}); + this["Fliplet"]["Widget"]["Templates"]["templates.thumbs"] = Handlebars.template({"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { var helper; return "
    \n \n
    "; + + "\" />\n
    "; },"useData":true}); \ No newline at end of file diff --git a/js/templates/no-thumb.interface.hbs b/js/templates/no-thumb.interface.hbs new file mode 100644 index 0000000..1211447 --- /dev/null +++ b/js/templates/no-thumb.interface.hbs @@ -0,0 +1,3 @@ +
    +
    Apple requires you to upload up to 4 screenshots of your app for {{ name }}. To generate your screenshots, go to App Settings.
    +
    \ No newline at end of file diff --git a/js/templates/thumb-containers.interface.hbs b/js/templates/thumb-containers.interface.hbs new file mode 100644 index 0000000..4fc9bd1 --- /dev/null +++ b/js/templates/thumb-containers.interface.hbs @@ -0,0 +1,6 @@ +{{#each this}} +
    +

    {{ name }}
    {{#each sizes}}{{#unless @first}} or {{/unless}}{{this.[0]}} × {{this.[1]}}{{/each}}

    +
    +
    +{{/each}} \ No newline at end of file diff --git a/js/templates/thumbs.interface.hbs b/js/templates/thumbs.interface.hbs index 09abe2c..79d3b70 100644 --- a/js/templates/thumbs.interface.hbs +++ b/js/templates/thumbs.interface.hbs @@ -1,3 +1,3 @@
    - +
    \ No newline at end of file From 4e01d1cb72788ed1c98fd903486fe3fb9b054af2 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Mon, 25 Mar 2019 18:40:20 +0000 Subject: [PATCH 146/318] Name change --- js/interface.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/js/interface.js b/js/interface.js index 3637661..a11c8c0 100644 --- a/js/interface.js +++ b/js/interface.js @@ -40,19 +40,19 @@ var hasFolders = false; var screenshotRequirements = [ { type: 'mobile', - name: 'iPhone 5.5-inch Display', + name: 'iPhone 5.5-inch', sizes: [[1242, 2208]], screenshots: [] }, { type: 'mobilex', - name: 'iPhone 6.5-inch Display', + name: 'iPhone 6.5-inch', sizes: [[1242, 2688]], screenshots: [] }, { type: 'tablet', - name: 'iPad Pro 12.9-inch Display', + name: 'iPad Pro 12.9-inch', sizes: [[2048, 2732], [2732, 2048]], screenshots: [] } From fd1ded2de4268b3830aef15b0172e86a2ab1c22a Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Wed, 27 Mar 2019 11:25:56 +0000 Subject: [PATCH 147/318] Re-introducing a bug to allow app submission Most of the time the screenshots are generated/uploaded in the correct size, so we're allowing this anomaly. --- js/interface.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/js/interface.js b/js/interface.js index a11c8c0..e4a785e 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1576,7 +1576,10 @@ function validateScreenshots() { return size[0] === screenshot.size[0] && size[1] === screenshot.size[1]; }); - if (screenshot.appId && supportedSize) { + // @BUG This should be using the && logic operator. Otherwise, it's ignoring the size check. + // However, there's an API bug where sizes are not stored using the correct pixel sizes, + // so we're allowing this bug for now. + if (screenshot.appId || supportedSize) { return; } From 9ffccd6db37ad7264ac77ef39e20e791d3afdb6d Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Wed, 27 Mar 2019 11:34:48 +0000 Subject: [PATCH 148/318] Adds GitHub issue link --- js/interface.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/interface.js b/js/interface.js index e4a785e..b0a1274 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1579,6 +1579,7 @@ function validateScreenshots() { // @BUG This should be using the && logic operator. Otherwise, it's ignoring the size check. // However, there's an API bug where sizes are not stored using the correct pixel sizes, // so we're allowing this bug for now. + // https://github.com/Fliplet/fliplet-studio/issues/4109 if (screenshot.appId || supportedSize) { return; } From 4434b85413dff4ca2d2f442a64bfaa985795f90c Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Sat, 30 Mar 2019 22:01:37 +0000 Subject: [PATCH 149/318] Moves common code together --- js/interface.js | 64 +++++++++++++++---------------------------------- 1 file changed, 19 insertions(+), 45 deletions(-) diff --git a/js/interface.js b/js/interface.js index b0a1274..c06a49a 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1218,9 +1218,25 @@ function searchCredentials(data) { method: 'POST', url: 'v1/organizations/' + organizationID + '/credentials/search', data: data - }) - .then(function (credentials) { - return Promise.resolve(credentials); + }).then(function (response) { + if (!response) { + return; + } + + var credentialKey; + var submissionsWithCred = _.filter(Object.keys(response), function (o) { + return response[o].hasCertificate === true; + }); + + credentialKey = _.max(submissionsWithCred, function (o) { + return response[o].updatedAt; + }); + + if (!credentialKey) { + return; + } + + return getCredential(credentialKey); }); } @@ -1269,27 +1285,6 @@ function refreshAppStoreOptions(devEmail, selectedTeamId, selectedTeamName) { email: devEmail, type: 'apple', teamId: selectedTeamId - }) - .then(function (response) { - var credentialKey; - var submissionsWithCred = _.filter(Object.keys(response), function (o) { - return response[o].hasCertificate === true; - }); - - if (submissionsWithCred) { - credentialKey = _.max(submissionsWithCred, function (o) { - return response[o].updatedAt; - }); - } - - if (credentialKey) { - return getCredential(credentialKey); - } - - return; - }) - .catch(function (error) { - return; }); }) .then(function (credential) { @@ -1355,27 +1350,6 @@ function refreshAppEnterpriseOptions(devEmail, selectedTeamId, selectedTeamName) email: devEmail, type: 'apple-enterprise', teamId: selectedTeamId - }) - .then(function (response) { - var credentialKey; - var submissionsWithCred = _.filter(Object.keys(response), function (o) { - return response[o].hasCertificate === true; - }); - - if (submissionsWithCred) { - credentialKey = _.max(submissionsWithCred, function (o) { - return response[o].updatedAt; - }); - } - - if (credentialKey) { - return getCredential(credentialKey); - } - - return; - }) - .catch(function (error) { - return; }); }) .then(function (credential) { From 9de3bdae6d03e0ecc9535e99263203a6b00935c0 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Sat, 30 Mar 2019 22:01:53 +0000 Subject: [PATCH 150/318] Adds error checking to prevent API error --- js/interface.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/js/interface.js b/js/interface.js index c06a49a..78593f2 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1439,19 +1439,20 @@ function getCompletedSubmissions(devEmail, teamId, teamName) { } function getCredential(credentialKey) { + return Promise.resolve(); + } + return Fliplet.API.request({ method: 'GET', url: 'v1/organizations/' + organizationID + '/credentials/' + credentialKey - }) - .then(function (credential) { + }).then(function (credential) { if (!credential || !credential.email) { // Valid credential email not found return Promise.resolve(); } return Promise.resolve(credential); - }) - .catch(function (error) { + }).catch(function (error) { if (error && error.status === 404) { // Credential not found return Promise.resolve(); From c8ed170072822d5e8ce72e0287942823e3c70adf Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Sat, 30 Mar 2019 22:02:11 +0000 Subject: [PATCH 151/318] Adds error checking to prevent API error --- js/interface.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/interface.js b/js/interface.js index 78593f2..40c7812 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1439,6 +1439,7 @@ function getCompletedSubmissions(devEmail, teamId, teamName) { } function getCredential(credentialKey) { + if (!credentialKey) { return Promise.resolve(); } From c1adcc98b6753f452dcd742f6fc112ad0b308595 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Tue, 30 Apr 2019 11:42:13 +0100 Subject: [PATCH 152/318] Wait for socket connection before login or getting teams (#92) Wait for socket connection before login or getting teams --- js/interface.js | 47 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/js/interface.js b/js/interface.js index 40c7812..56dea35 100644 --- a/js/interface.js +++ b/js/interface.js @@ -61,8 +61,9 @@ var hasAllScreenshots = false; var screenshotValidationNotRequired = false; var spinner = ''; +var socketRequiresLogin = true; var socket = Fliplet.Socket({ - login: true + login: socketRequiresLogin }); var socketClientId; @@ -74,6 +75,29 @@ String.prototype.toCamelCase = function () { }).replace(/([^A-Z-a-z])/g, '').toLowerCase(); }; +function socketIsReady() { + return socket.connected && (!socketRequiresLogin || socket.loggedIn); +} + +function waitForSocketConnection() { + if (socketIsReady()) { + return Promise.resolve(); + } + + var interval; + + return new Promise(function (resolve) { + interval = setInterval(function () { + if (!socketIsReady()) { + return; + } + + clearInterval(interval); + resolve(); + }, 200); + }); +} + function createBundleID(orgName, appName) { return $.ajax({ url: "https://itunes.apple.com/lookup?bundleId=com." + orgName + "." + appName, @@ -1196,19 +1220,22 @@ function cloneCredentials(credentialKey, submission, saveData) { function setCredentials(id, data, verify) { verify = typeof verify === 'undefined' ? true : verify; - return Fliplet.API.request({ - method: 'PUT', - url: 'v1/organizations/' + organizationID + '/credentials/submission-' + id + '?verify=' + verify, - data: data + return waitForSocketConnection().then(function () { + return Fliplet.API.request({ + method: 'PUT', + url: 'v1/organizations/' + organizationID + '/credentials/submission-' + id + '?verify=' + verify, + data: data + }); }); } function getTeams(id, isItunes) { - return Fliplet.API.request({ - method: 'GET', - url: 'v1/organizations/' + organizationID + '/credentials/submission-' + id + '/teams?itunes=' + isItunes - }) - .then(function (result) { + return waitForSocketConnection().then(function () { + return Fliplet.API.request({ + method: 'GET', + url: 'v1/organizations/' + organizationID + '/credentials/submission-' + id + '/teams?itunes=' + isItunes + }); + }).then(function (result) { return Promise.resolve(result.teams); }); } From 06d091629bdef5f4791425e28a6d9358d74085cc Mon Sep 17 00:00:00 2001 From: Nicholas Valbusa Date: Mon, 20 May 2019 14:42:17 +0200 Subject: [PATCH 153/318] validate version number --- js/interface.js | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/js/interface.js b/js/interface.js index 56dea35..4b7bb57 100644 --- a/js/interface.js +++ b/js/interface.js @@ -106,7 +106,7 @@ function createBundleID(orgName, appName) { } function incrementVersionNumber(versionNumber) { - var splitNumber = versionNumber.split('.'); + var splitNumber = _.compact(versionNumber.split('.')); var arrLength = splitNumber.length; while (arrLength--) { @@ -1566,6 +1566,10 @@ function checkGroupErrors() { }); } +function isValidVersion(version) { + return /^[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2}$/.test(version); +} + function validateScreenshots() { var imageErrors = []; var supportedFormats = _.uniqBy(_.concat.apply(null, _.map(screenshotRequirements, 'sizes')), @@ -2424,6 +2428,13 @@ $('#appStoreConfiguration').validator().on('submit', function (event) { event.preventDefault(); + if (!isValidVersion($('[name="fl-store-versionNumber"]').val())) { + Fliplet.Modal.alert({ + message: 'The version number is incorrect: you must use a period-separated list of three non-negative integers.' + }); + return; + } + if ($('[name="fl-store-screenshots"]:checked').val() === 'new' && !hasAllScreenshots) { Fliplet.Modal.alert({ message: 'You need to add screenshots before submitting' @@ -2518,6 +2529,13 @@ $('#enterpriseConfiguration').validator().on('submit', function (event) { event.preventDefault(); + if (!isValidVersion($('[name="fl-ent-versionNumber"]').val())) { + Fliplet.Modal.alert({ + message: 'The version number is incorrect: you must use a period-separated list of three non-negative integers.' + }); + return; + } + if (!enterpriseManual && !enterpriseLoggedIn) { Fliplet.Modal.alert({ message: 'Please log in with the Apple Developer Account or choose to enter the data manually.' @@ -2592,6 +2610,13 @@ $('#unsignedConfiguration').validator().on('submit', function (event) { event.preventDefault(); + if (!isValidVersion($('[name="fl-uns-versionNumber"]').val())) { + Fliplet.Modal.alert({ + message: 'The version number is incorrect: you must use a period-separated list of three non-negative integers.' + }); + return; + } + if (appInfo && appInfo.productionAppId) { if (allAppData.indexOf('unsigned') > -1) { var message = 'Are you sure you wish to update your published app?'; From 673e1cba4deeffad50fa3c5cfb64c7c68663d67a Mon Sep 17 00:00:00 2001 From: Nicholas Valbusa Date: Mon, 20 May 2019 14:44:34 +0200 Subject: [PATCH 154/318] errors refactor --- js/interface.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/js/interface.js b/js/interface.js index 4b7bb57..0009f40 100644 --- a/js/interface.js +++ b/js/interface.js @@ -67,6 +67,12 @@ var socket = Fliplet.Socket({ }); var socketClientId; +/* ERROR MESSAGES */ + +var ERRORS = { + INVALID_VERSION: 'The version number is incorrect: you must use a period-separated list of three non-negative integers.' +}; + /* FUNCTIONS */ String.prototype.toCamelCase = function () { return this.replace(/^([A-Z])|[^A-Za-z]+(\w)/g, function (match, p1, p2, offset) { @@ -2430,7 +2436,7 @@ $('#appStoreConfiguration').validator().on('submit', function (event) { if (!isValidVersion($('[name="fl-store-versionNumber"]').val())) { Fliplet.Modal.alert({ - message: 'The version number is incorrect: you must use a period-separated list of three non-negative integers.' + message: ERRORS.INVALID_VERSION }); return; } @@ -2531,7 +2537,7 @@ $('#enterpriseConfiguration').validator().on('submit', function (event) { if (!isValidVersion($('[name="fl-ent-versionNumber"]').val())) { Fliplet.Modal.alert({ - message: 'The version number is incorrect: you must use a period-separated list of three non-negative integers.' + message: ERRORS.INVALID_VERSION }); return; } @@ -2612,7 +2618,7 @@ $('#unsignedConfiguration').validator().on('submit', function (event) { if (!isValidVersion($('[name="fl-uns-versionNumber"]').val())) { Fliplet.Modal.alert({ - message: 'The version number is incorrect: you must use a period-separated list of three non-negative integers.' + message: ERRORS.INVALID_VERSION }); return; } From 8345013aec8e0fbe565ed802f6537c0aaf9bf346 Mon Sep 17 00:00:00 2001 From: Nicholas Valbusa Date: Mon, 20 May 2019 15:30:11 +0200 Subject: [PATCH 155/318] copy update --- interface.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface.html b/interface.html index 91743c0..c132255 100644 --- a/interface.html +++ b/interface.html @@ -720,7 +720,7 @@

    App version and bundle ID

    -

    The recommended format for version number is 1.0.0. With a maximum value of 99 per number.

    +

    The required format for version number is 1.0.0. With a maximum value of 99 per number.

    @@ -1418,7 +1418,7 @@

    App version and bundle ID

    -

    The recommended format for version number is 1.0.0. With a maximum value of 99 per number.

    +

    The required format for version number is 1.0.0. With a maximum value of 99 per number.

    @@ -1533,7 +1533,7 @@
    From b89d5ba2d76264ed8ebe30c9d06e4082ad0cb6d4 Mon Sep 17 00:00:00 2001 From: Nicholas Valbusa Date: Mon, 20 May 2019 16:37:32 +0200 Subject: [PATCH 156/318] copy update --- js/interface.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/interface.js b/js/interface.js index 0009f40..82ddeb3 100644 --- a/js/interface.js +++ b/js/interface.js @@ -70,7 +70,7 @@ var socketClientId; /* ERROR MESSAGES */ var ERRORS = { - INVALID_VERSION: 'The version number is incorrect: you must use a period-separated list of three non-negative integers.' + INVALID_VERSION: 'The version number is incorrect. Please use a 3-part version number such as 1.0.0 where each part is no larger than 99.' }; /* FUNCTIONS */ From 2fd54ed8f54bb6ffc670dae13dfaac009a7e268d Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Thu, 27 Jun 2019 11:57:08 +0100 Subject: [PATCH 157/318] Removes unnecessary validation checking (#94) The function callers are already running validation checks --- js/interface.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/js/interface.js b/js/interface.js index 82ddeb3..363d541 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1479,13 +1479,6 @@ function getCredential(credentialKey) { return Fliplet.API.request({ method: 'GET', url: 'v1/organizations/' + organizationID + '/credentials/' + credentialKey - }).then(function (credential) { - if (!credential || !credential.email) { - // Valid credential email not found - return Promise.resolve(); - } - - return Promise.resolve(credential); }).catch(function (error) { if (error && error.status === 404) { // Credential not found From e2a28b677b6ada1fcd0a29499d1acc81a8660c67 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Mon, 1 Jul 2019 11:42:25 +0100 Subject: [PATCH 158/318] Create keyword token when blurring from the input field (#95) --- js/interface.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/js/interface.js b/js/interface.js index 363d541..97e8b92 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1527,7 +1527,9 @@ function init() { }); }); - $('#fl-store-keywords').tokenfield(); + $('#fl-store-keywords').tokenfield({ + createTokensOnBlur: true + }); /* APP ICON */ if (appIcon) { From 982a1ca50c3a87ed475b95a95cdc96dd48965460 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Mon, 8 Jul 2019 12:04:23 +0100 Subject: [PATCH 159/318] Allow all non-enterprise accounts to submit app store apps (#96) --- js/interface.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/js/interface.js b/js/interface.js index 97e8b92..29f7dc6 100644 --- a/js/interface.js +++ b/js/interface.js @@ -357,7 +357,11 @@ function loadAppStoreTeams(devEmail) { return itcTeam.team_name === team.name; }); - return team.type === "Company/Organization" && !_.isUndefined(itunesTeam); + if (itunesTeam) { + return false; + } + + return team.type !== "In-House"; }); var options = ['']; From 4f5b8df74bf5cb3eff7d7cb714ab2718ca982032 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Mon, 8 Jul 2019 21:59:53 +0100 Subject: [PATCH 160/318] Typo --- js/interface.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/interface.js b/js/interface.js index 29f7dc6..3299ac7 100644 --- a/js/interface.js +++ b/js/interface.js @@ -357,7 +357,7 @@ function loadAppStoreTeams(devEmail) { return itcTeam.team_name === team.name; }); - if (itunesTeam) { + if (!itunesTeam) { return false; } From c51c420e8a0bef1023f41ec64816a3e2e7bcce62 Mon Sep 17 00:00:00 2001 From: Nicholas Valbusa Date: Tue, 30 Jul 2019 19:25:22 +0200 Subject: [PATCH 161/318] added warning for certificates duration --- interface.html | 1 + 1 file changed, 1 insertion(+) diff --git a/interface.html b/interface.html index c132255..57d0e41 100644 --- a/interface.html +++ b/interface.html @@ -1354,6 +1354,7 @@

    Apple developer account details and distribution certificates

    +
    Certificates generated for iOS last up to 12 months and must be regenerated before they expire.
    - + +
    diff --git a/js/interface.js b/js/interface.js index 3299ac7..671adf4 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1571,6 +1571,11 @@ function checkGroupErrors() { }); } +// We set required attribute to 'demo password' only if 'demo user' field is not empty +function checkDemoUser() { + $('#fl-store-revDemoPass').prop('required', $('#fl-store-revDemoUser').val() !== ''); +} + function isValidVersion(version) { return /^[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2}$/.test(version); } @@ -2257,6 +2262,17 @@ $('#fl-store-2fa-select, #fl-ent-2fa-select').on('change', function (e) { socket.to(socketClientId).emit('aab.apple.login.2fa.device', e.target.value); }); +// When app is loaded we check if user previosly saved 'demo user' but not 'demo user password'. +Fliplet().then(function () { + checkDemoUser(); +}); + +// After user blur from 'demo user' field we check again to make sure that the field is empty. +// If field is empty we remove required attribute. +$('#fl-store-revDemoUser').on('blur', function () { + checkDemoUser(); +}); + $('.2fa-code-store-button, .2fa-code-ent-button').on('click', function (e) { var code = $(this).parents('.form-group').prev().find('.form-control').val(); From c909999bda556c60a6b669a1b1edea01f5215a64 Mon Sep 17 00:00:00 2001 From: YaroslavOvdii Date: Fri, 9 Aug 2019 18:47:16 +0300 Subject: [PATCH 164/318] Moved checkDemoUser to the end of the data loading from API --- js/interface.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/js/interface.js b/js/interface.js index 671adf4..8e5427e 100644 --- a/js/interface.js +++ b/js/interface.js @@ -28,6 +28,7 @@ var enterpriseSubmission = {}; var unsignedSubmission = {}; var notificationSettings = {}; var appInfo; +var demoUser; var statusTableTemplate = $('#status-table-template').html(); var $statusAppStoreTableElement = $('.app-build-appstore-status-holder'); var $statusEnterpriseTableElement = $('.app-build-enterprise-status-holder'); @@ -271,6 +272,12 @@ function loadAppStoreData() { $('[name="' + name + '"]').val((typeof appStoreSubmission.data[name] !== "undefined") ? appStoreSubmission.data[name] : ''); }); + // Saving 'demo user' value from API to compare it in checkDemoUser function + demoUser = appStoreSubmission.data['fl-store-revDemoUser']; + + // When all data is loaded we can check if demo user was saved before + checkDemoUser(); + if (appName !== '' && appIcon && (checkHasAllScreenshots() || screenshotValidationNotRequired)) { if (appSettings.splashScreen && appSettings.splashScreen.size && (appSettings.splashScreen.size[0] && appSettings.splashScreen.size[1]) < 2732) { $('.app-details-appStore .app-splash-screen').addClass('has-warning'); @@ -1573,6 +1580,9 @@ function checkGroupErrors() { // We set required attribute to 'demo password' only if 'demo user' field is not empty function checkDemoUser() { + // When google tries to auto-fill 'demo user' field, we checking data fron API and delete google auto-fill + // if no saved data for this field + $('#fl-store-revDemoUser').val(demoUser ? demoUser : ''); $('#fl-store-revDemoPass').prop('required', $('#fl-store-revDemoUser').val() !== ''); } @@ -2262,11 +2272,6 @@ $('#fl-store-2fa-select, #fl-ent-2fa-select').on('change', function (e) { socket.to(socketClientId).emit('aab.apple.login.2fa.device', e.target.value); }); -// When app is loaded we check if user previosly saved 'demo user' but not 'demo user password'. -Fliplet().then(function () { - checkDemoUser(); -}); - // After user blur from 'demo user' field we check again to make sure that the field is empty. // If field is empty we remove required attribute. $('#fl-store-revDemoUser').on('blur', function () { From 9e71ff4ed4eaed35a1f4058e21d91d687ab12100 Mon Sep 17 00:00:00 2001 From: YaroslavOvdii Date: Fri, 16 Aug 2019 15:19:10 +0300 Subject: [PATCH 165/318] Made changes as was requested --- js/interface.js | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/js/interface.js b/js/interface.js index 8e5427e..968fce3 100644 --- a/js/interface.js +++ b/js/interface.js @@ -29,6 +29,7 @@ var unsignedSubmission = {}; var notificationSettings = {}; var appInfo; var demoUser; +var userInput; var statusTableTemplate = $('#status-table-template').html(); var $statusAppStoreTableElement = $('.app-build-appstore-status-holder'); var $statusEnterpriseTableElement = $('.app-build-enterprise-status-holder'); @@ -1582,8 +1583,11 @@ function checkGroupErrors() { function checkDemoUser() { // When google tries to auto-fill 'demo user' field, we checking data fron API and delete google auto-fill // if no saved data for this field - $('#fl-store-revDemoUser').val(demoUser ? demoUser : ''); - $('#fl-store-revDemoPass').prop('required', $('#fl-store-revDemoUser').val() !== ''); + var $demoUserFiled = $('#fl-store-revDemoUser'); + if (!userInput) { + $demoUserFiled.val(demoUser ? demoUser : ''); + } + $('#fl-store-revDemoPass').prop('required', $demoUserFiled.val() !== ''); } function isValidVersion(version) { @@ -2272,9 +2276,18 @@ $('#fl-store-2fa-select, #fl-ent-2fa-select').on('change', function (e) { socket.to(socketClientId).emit('aab.apple.login.2fa.device', e.target.value); }); +Fliplet().then(function () { + checkDemoUser(); +}); + +// This listener need that we can understand that it is a user entering data but not an any password managers. +$('#fl-store-revDemoUser').on('keyup', function (event) { + userInput = event && event.key || false; +}); + // After user blur from 'demo user' field we check again to make sure that the field is empty. // If field is empty we remove required attribute. -$('#fl-store-revDemoUser').on('blur', function () { +$('#fl-store-revDemoUser').on('change', function () { checkDemoUser(); }); From 5e2cf92b39920329fab602106a3f8d1ad0b265ec Mon Sep 17 00:00:00 2001 From: YaroslavOvdii Date: Fri, 16 Aug 2019 15:36:45 +0300 Subject: [PATCH 166/318] Saving form information when user go to another modal --- js/interface.js | 99 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 64 insertions(+), 35 deletions(-) diff --git a/js/interface.js b/js/interface.js index 3299ac7..8a1d4bd 100644 --- a/js/interface.js +++ b/js/interface.js @@ -670,7 +670,7 @@ function submissionBuild(appSubmission, origin) { function save(origin, submission) { - Fliplet.App.Submissions.get() + return Fliplet.App.Submissions.get() .then(function (submissions) { var savedSubmission = _.find(submissions, function (sub) { return sub.id === submission.id; @@ -707,7 +707,6 @@ function save(origin, submission) { if (origin === "unsigned") { unsignedSubmission = newSubmission; } - return cloneCredentialsPromise.then(function () { return Fliplet.App.Submissions.update(newSubmission.id, newSubmission.data); }).then(function () { @@ -755,7 +754,7 @@ function requestBuild(origin, submission) { submission.data.appIcon = appIcon; submission.data.legacyBuild = appSettings.legacyBuild || false; - Fliplet.App.Submissions.get() + return Fliplet.App.Submissions.get() .then(function (submissions) { var savedSubmission = _.find(submissions, function (sub) { return sub.id === submission.id; @@ -1030,9 +1029,9 @@ function saveAppStoreData(request) { savePushData(true); if (request) { - requestBuild('appStore', appStoreSubmission); + return requestBuild('appStore', appStoreSubmission); } else { - save('appStore', appStoreSubmission); + return save('appStore', appStoreSubmission); } } @@ -1120,9 +1119,9 @@ function saveEnterpriseData(request) { savePushData(true); if (request) { - requestBuild('enterprise', enterpriseSubmission); + return requestBuild('enterprise', enterpriseSubmission); } else { - save('enterprise', enterpriseSubmission); + return save('enterprise', enterpriseSubmission); } }); } else { @@ -1133,9 +1132,9 @@ function saveEnterpriseData(request) { savePushData(true); if (request) { - requestBuild('enterprise', enterpriseSubmission); + return requestBuild('enterprise', enterpriseSubmission); } else { - save('enterprise', enterpriseSubmission); + return save('enterprise', enterpriseSubmission); } } } @@ -1157,9 +1156,9 @@ function saveUnsignedData(request) { unsignedSubmission.data = data; if (request) { - requestBuild('unsigned', unsignedSubmission); + return requestBuild('unsigned', unsignedSubmission); } else { - save('unsigned', unsignedSubmission); + return save('unsigned', unsignedSubmission); } } @@ -1211,6 +1210,19 @@ function savePushData(silentSave) { }); } +function saveProgressOnClose () { + var savingFunctions = { + "appstore-control": saveAppStoreData, + "enterprise-control": saveEnterpriseData, + "unsigned-control": saveUnsignedData + } + + //Finding out active tab to use correct save method + var activeTabId = $(".nav.nav-tabs li.active").prop("id"); + + return savingFunctions[activeTabId]() +} + function cloneCredentials(credentialKey, submission, saveData) { return Fliplet.API.request({ method: 'POST', @@ -2371,37 +2383,54 @@ $('[name="fl-store-keywords"]').on('tokenfield:createtoken', function (e) { $('.redirectToSettings, [data-change-settings]').on('click', function (event) { event.preventDefault(); - Fliplet.Studio.emit('close-overlay', { - name: 'publish-apple' - }); + saveProgressOnClose().then(function () { + Fliplet.Studio.emit('close-overlay', { + name: 'publish-apple' + }); + + Fliplet.Studio.emit('overlay', { + name: 'app-settings', + options: { + size: 'large', + title: 'App Settings', + section: 'appSettingsGeneral', + appId: Fliplet.Env.get('appId') + } + }); + }) + .catch(function (err) { + Fliplet.Modal.alert({ + message: Fliplet.parseError(err) + }) + }) - Fliplet.Studio.emit('overlay', { - name: 'app-settings', - options: { - size: 'large', - title: 'App Settings', - section: 'appSettingsGeneral', - appId: Fliplet.Env.get('appId') - } - }); }); $(document).on('click', '[data-change-assets]', function (event) { event.preventDefault(); - Fliplet.Studio.emit('close-overlay', { - name: 'publish-apple' - }); + saveProgressOnClose().then(function () { + Fliplet.Studio.emit('close-overlay', { + name: 'publish-apple' + }); + + Fliplet.Studio.emit('overlay', { + name: 'app-settings', + options: { + size: 'large', + title: 'App Settings', + section: 'launchAssets', + appId: Fliplet.Env.get('appId') + } + }); + }) + .catch(function (err) { + Fliplet.Modal.alert({ + message: Fliplet.parseError(err) + }) + }) + - Fliplet.Studio.emit('overlay', { - name: 'app-settings', - options: { - size: 'large', - title: 'App Settings', - section: 'launchAssets', - appId: Fliplet.Env.get('appId') - } - }); }); $('#appStoreConfiguration, #enterpriseConfiguration, #unsignedConfiguration').on('validated.bs.validator', function () { From ffbf221ae0294e143942f5cab3f0669f1eb02f17 Mon Sep 17 00:00:00 2001 From: YaroslavOvdii Date: Mon, 19 Aug 2019 13:55:56 +0300 Subject: [PATCH 167/318] fix --- js/interface.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/js/interface.js b/js/interface.js index 8a1d4bd..013f97b 100644 --- a/js/interface.js +++ b/js/interface.js @@ -2397,12 +2397,11 @@ $('.redirectToSettings, [data-change-settings]').on('click', function (event) { appId: Fliplet.Env.get('appId') } }); - }) - .catch(function (err) { + }).catch(function (err) { Fliplet.Modal.alert({ message: Fliplet.parseError(err) }) - }) + }); }); @@ -2423,14 +2422,12 @@ $(document).on('click', '[data-change-assets]', function (event) { appId: Fliplet.Env.get('appId') } }); - }) - .catch(function (err) { + }).catch(function (err) { Fliplet.Modal.alert({ message: Fliplet.parseError(err) }) - }) - - + }); + }); $('#appStoreConfiguration, #enterpriseConfiguration, #unsignedConfiguration').on('validated.bs.validator', function () { From 92ea86451ede7c38a6d64fb8a16e8027092b8a9d Mon Sep 17 00:00:00 2001 From: YaroslavOvdii Date: Wed, 21 Aug 2019 13:27:25 +0300 Subject: [PATCH 168/318] add the opportunity to use auto-fill only when user want this --- js/interface.js | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/js/interface.js b/js/interface.js index 968fce3..c0eae5f 100644 --- a/js/interface.js +++ b/js/interface.js @@ -29,7 +29,8 @@ var unsignedSubmission = {}; var notificationSettings = {}; var appInfo; var demoUser; -var userInput; +var userInput = false; +var autoFill = 0; var statusTableTemplate = $('#status-table-template').html(); var $statusAppStoreTableElement = $('.app-build-appstore-status-holder'); var $statusEnterpriseTableElement = $('.app-build-enterprise-status-holder'); @@ -1581,11 +1582,15 @@ function checkGroupErrors() { // We set required attribute to 'demo password' only if 'demo user' field is not empty function checkDemoUser() { - // When google tries to auto-fill 'demo user' field, we checking data fron API and delete google auto-fill + // When google tries to auto-fill 'demo user' field, we checking data from API and delete google auto-fill // if no saved data for this field + // To allow a user to use auto-fill from google but disallow google to put the information to the field by itself. + // We check how many times use google auto-fill after numerous tries found out that google inserts data to this input + // only three times at a row, so, therefore, the fourth time it's a user trying to input information from auto-fill. var $demoUserFiled = $('#fl-store-revDemoUser'); - if (!userInput) { + if (!userInput && autoFill < 3) { $demoUserFiled.val(demoUser ? demoUser : ''); + autoFill++; } $('#fl-store-revDemoPass').prop('required', $demoUserFiled.val() !== ''); } @@ -2280,14 +2285,11 @@ Fliplet().then(function () { checkDemoUser(); }); -// This listener need that we can understand that it is a user entering data but not an any password managers. -$('#fl-store-revDemoUser').on('keyup', function (event) { - userInput = event && event.key || false; -}); - // After user blur from 'demo user' field we check again to make sure that the field is empty. // If field is empty we remove required attribute. -$('#fl-store-revDemoUser').on('change', function () { +$('#fl-store-revDemoUser').on('input', function (event) { + userInput = event.originalEvent.inputType || false; + checkDemoUser(); }); From 7250bd4a65acd4f5d5064c78639c2eec048697db Mon Sep 17 00:00:00 2001 From: Nicholas Valbusa Date: Wed, 4 Sep 2019 19:13:41 +0200 Subject: [PATCH 169/318] interface to upload firebase file --- interface.html | 50 ++++++++++++++++++++++ js/interface.js | 107 ++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 149 insertions(+), 8 deletions(-) diff --git a/interface.html b/interface.html index 3a79e79..7a2bdf8 100644 --- a/interface.html +++ b/interface.html @@ -740,6 +740,22 @@

    App version and bundle ID

    + +

    Google Firebase (optional)

    +
    +
    + +

    Register your app on Firebase and download the config file from the Firebase project settings.

    +
    +
    + +
    + +
    +
    +
    @@ -1439,6 +1455,23 @@

    App version and bundle ID

    + +

    Google Firebase (optional)

    +
    +
    + +

    Register your app on Firebase and download the config file from the Firebase project settings.

    +
    +
    + +
    + +
    +
    +
    + @@ -1554,6 +1587,23 @@

    Google Firebase (optional)

    +
    +
    + +

    Register your app on Firebase and download the config file from the Firebase project settings.

    +
    +
    + +
    + +
    +
    +
    + diff --git a/js/interface.js b/js/interface.js index 013f97b..bb84d85 100644 --- a/js/interface.js +++ b/js/interface.js @@ -15,6 +15,9 @@ var previousAppStoreSubmission = {}; var previousEnterpriseStoreSubmission = {}; var appStorePreviousCredential = undefined; var appStoreFileField = undefined; +var appStoreFirebaseFileField = undefined; +var enterpriseFirebaseFileField = undefined; +var unsignedFirebaseFileField = undefined; var appStoreTeamId = undefined; var enterprisePreviousCredential = undefined; var enterpriseFileField = undefined; @@ -111,6 +114,34 @@ function createBundleID(orgName, appName) { }); } +function saveFirebaseSettings(origin) { + if (origin === 'appStore' && appStoreFirebaseFileField && appStoreFirebaseFileField.files[0]) { + var formData = new FormData(); + + formData.append('firebase', appStoreFirebaseFileField.files[0]); + + return setFirebaseConfigFile(appStoreSubmission.id, formData); + } + + if (origin === 'enterprise' && enterpriseFirebaseFileField && enterpriseFirebaseFileField.files[0]) { + var formData = new FormData(); + + formData.append('firebase', enterpriseFirebaseFileField.files[0]); + + return setFirebaseConfigFile(enterpriseSubmission.id, formData); + } + + if (origin === 'unsigned' && unsignedFirebaseFileField && unsignedFirebaseFileField.files[0]) { + var formData = new FormData(); + + formData.append('firebase', unsignedFirebaseFileField.files[0]); + + return setFirebaseConfigFile(enterpriseSubmission.id, formData); + } + + return Promise.resolve(); +} + function incrementVersionNumber(versionNumber) { var splitNumber = _.compact(versionNumber.split('.')); var arrLength = splitNumber.length; @@ -249,6 +280,11 @@ function loadAppStoreData() { return; } + // Firebase + if (name === 'fl-store-firebase') { + return; + } + /* Manual release */ if (name === "fl-store-manualRelease") { if (!_.isUndefined(appStoreSubmission.data[name])) { @@ -443,6 +479,11 @@ function loadEnterpriseData() { return; } + // Firebase + if (name === 'fl-ent-firebase') { + return; + } + $('[name="' + name + '"]').val((typeof enterpriseSubmission.data[name] !== "undefined") ? enterpriseSubmission.data[name] : ''); }); @@ -571,6 +612,11 @@ function loadUnsignedData() { return; } + // Firebase + if (name === 'fl-uns-firebase') { + return; + } + $('[name="' + name + '"]').val((typeof unsignedSubmission.data[name] !== "undefined") ? unsignedSubmission.data[name] : ''); }); @@ -612,8 +658,9 @@ function loadPushNotesData() { } function submissionBuild(appSubmission, origin) { - Fliplet.App.Submissions.build(appSubmission.id).then(function (builtSubmission) { - + saveFirebaseSettings(origin).then(function () { + return Fliplet.App.Submissions.build(appSubmission.id); + }).then(function (builtSubmission) { if (origin === "appStore") { appStoreSubmission = builtSubmission.submission; // Auto increments the version number and saves the submission @@ -768,6 +815,7 @@ function requestBuild(origin, submission) { if (submission.data.hasOwnProperty('fl-credentials')) { delete submission.data['fl-credentials']; } + return Fliplet.App.Submissions.create({ platform: 'ios', data: $.extend(true, submission.data, { @@ -800,6 +848,8 @@ function requestBuild(origin, submission) { }); } + // TODO: APPEND FIREBASE FILE? + if (origin === "appStore" && appStoreSubmission.data['fl-store-distribution'] === 'upload-file') { var formData = new FormData(); var fileName = appStoreFileField.value.replace(/\\/g, '/').replace(/.*\//, ''); @@ -871,6 +921,8 @@ function requestBuild(origin, submission) { }); } + // Code for first submission of this type + setCredentials(appStoreSubmission.id, { appPassword: $('#fl-store-appPassword').val().trim() }, false).then(function () { @@ -1216,7 +1268,7 @@ function saveProgressOnClose () { "enterprise-control": saveEnterpriseData, "unsigned-control": saveUnsignedData } - + //Finding out active tab to use correct save method var activeTabId = $(".nav.nav-tabs li.active").prop("id"); @@ -1529,6 +1581,16 @@ function setCertificateP12(id, file) { }); } +function setFirebaseConfigFile(id, file) { + return Fliplet.API.request({ + method: 'PUT', + url: 'v1/organizations/' + organizationID + '/credentials/submission-' + id + '?fileName=firebase', + data: file, + contentType: false, + processData: false + }); +} + function revokeCertificate(id, certId) { return Fliplet.API.request({ method: 'DELETE', @@ -1711,7 +1773,7 @@ function checkSubmissionStatus(origin, iosSubmissions) { // Default copy for testing status for different users if (submission.status === 'ready-for-testing') { - if (userInfo.user && (userInfo.user.isAdmin || userInfo.user.isImpersonating)) { + if (userInfo && userInfo.user && (userInfo.user.isAdmin || userInfo.user.isImpersonating)) { // Fliplet users build.testingStatus = 'Ready for testing'; build.testingMessage = 'App is ready for testing'; @@ -1756,7 +1818,7 @@ function checkSubmissionStatus(origin, iosSubmissions) { build.message = submission.result.message; } - if (userInfo.user && (userInfo.user.isAdmin || userInfo.user.isImpersonating)) { + if (userInfo && userInfo.user && (userInfo.user.isAdmin || userInfo.user.isImpersonating)) { build.debugFileUrl = debugHtmlPage ? debugHtmlPage.url : ''; } @@ -2387,7 +2449,7 @@ $('.redirectToSettings, [data-change-settings]').on('click', function (event) { Fliplet.Studio.emit('close-overlay', { name: 'publish-apple' }); - + Fliplet.Studio.emit('overlay', { name: 'app-settings', options: { @@ -2412,7 +2474,7 @@ $(document).on('click', '[data-change-assets]', function (event) { Fliplet.Studio.emit('close-overlay', { name: 'publish-apple' }); - + Fliplet.Studio.emit('overlay', { name: 'app-settings', options: { @@ -2427,7 +2489,7 @@ $(document).on('click', '[data-change-assets]', function (event) { message: Fliplet.parseError(err) }) }); - + }); $('#appStoreConfiguration, #enterpriseConfiguration, #unsignedConfiguration').on('validated.bs.validator', function () { @@ -2887,6 +2949,35 @@ $('#fl-store-certificate').on('change', function () { } }); +// Firebase + +$('#fl-store-firebase').on('change', function () { + appStoreFirebaseFileField = this; + var fileName = this.value.replace(/\\/g, '/').replace(/.*\//, ''); + + if (this.files && this.files[0]) { + $('#fl-store-firebase-uploaded').html('File uploaded: ' + fileName + '').removeClass('hidden'); + } +}); + +$('#fl-ent-firebase').on('change', function () { + enterpriseFirebaseFileField = this; + var fileName = this.value.replace(/\\/g, '/').replace(/.*\//, ''); + + if (this.files && this.files[0]) { + $('#fl-ent-firebase-uploaded').html('File uploaded: ' + fileName + '').removeClass('hidden'); + } +}); + +$('#fl-uns-firebase').on('change', function () { + unsignedFirebaseFileField = this; + var fileName = this.value.replace(/\\/g, '/').replace(/.*\//, ''); + + if (this.files && this.files[0]) { + $('#fl-uns-firebase-uploaded').html('File uploaded: ' + fileName + '').removeClass('hidden'); + } +}); + $('.appStore-replace-cert').on('click', function () { var $this = $(this); $(this).html('Replacing ' + spinner); From 9b57831eede33de2c752e7b51f463e98ddd8d5ca Mon Sep 17 00:00:00 2001 From: Nicholas Valbusa Date: Wed, 4 Sep 2019 19:16:39 +0200 Subject: [PATCH 170/318] tweaks --- js/interface.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/js/interface.js b/js/interface.js index bb84d85..bf8dcff 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1027,8 +1027,8 @@ function saveAppStoreData(request) { value = value.trim(); } - if (name === 'fl-store-appPassword') { - // Skip saving app-specific password + if (name === 'fl-store-appPassword' || name === 'fl-store-firebase') { + // Skip saving app-specific password and Firebase config file // This will be saved in credentials return; } @@ -1112,6 +1112,10 @@ function saveEnterpriseData(request) { return; } + if (name === 'fl-ent-firebase') { + return; // saved in credentials + } + if (name === 'fl-ent-teamId') { if (enterpriseManual) { data[name] = value; @@ -1196,6 +1200,11 @@ function saveUnsignedData(request) { $('#unsignedConfiguration [name]').each(function (i, el) { var name = $(el).attr("name"); + + if (name === 'fl-uns-firebase') { + return; // saved in credentials + } + var value = $(el).val(); if (typeof value === 'string') { From 58b4df26761cb45a42a32364fd98eaf47033e0b0 Mon Sep 17 00:00:00 2001 From: Nicholas Valbusa Date: Wed, 4 Sep 2019 19:19:53 +0200 Subject: [PATCH 171/318] typo --- js/interface.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/interface.js b/js/interface.js index bf8dcff..52c0665 100644 --- a/js/interface.js +++ b/js/interface.js @@ -136,7 +136,7 @@ function saveFirebaseSettings(origin) { formData.append('firebase', unsignedFirebaseFileField.files[0]); - return setFirebaseConfigFile(enterpriseSubmission.id, formData); + return setFirebaseConfigFile(unsignedSubmission.id, formData); } return Promise.resolve(); From 1968c7e4989448f9f8a8e5d0f4e3711a31c9007e Mon Sep 17 00:00:00 2001 From: Nicholas Valbusa Date: Wed, 4 Sep 2019 19:25:48 +0200 Subject: [PATCH 172/318] save unsigned credentials --- js/interface.js | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/js/interface.js b/js/interface.js index 52c0665..46f991b 100644 --- a/js/interface.js +++ b/js/interface.js @@ -741,19 +741,19 @@ function save(origin, submission) { .then(function (newSubmission) { var cloneCredentialsPromise = Promise.resolve(); + newSubmission.data['fl-credentials'] = 'submission-' + newSubmission.id; + if (origin === "appStore") { - newSubmission.data['fl-credentials'] = 'submission-' + newSubmission.id; appStoreSubmission = newSubmission; cloneCredentialsPromise = cloneCredentials(previousCredentials, appStoreSubmission); - } - if (origin === "enterprise") { - newSubmission.data['fl-credentials'] = 'submission-' + newSubmission.id; + } else if (origin === "enterprise") { enterpriseSubmission = newSubmission; cloneCredentialsPromise = cloneCredentials(previousCredentials, enterpriseSubmission); - } - if (origin === "unsigned") { + } else if (origin === "unsigned") { unsignedSubmission = newSubmission; + cloneCredentialsPromise = cloneCredentials(previousCredentials, unsignedSubmission); } + return cloneCredentialsPromise.then(function () { return Fliplet.App.Submissions.update(newSubmission.id, newSubmission.data); }).then(function () { @@ -1214,6 +1214,8 @@ function saveUnsignedData(request) { data[name] = value; }); + data['fl-credentials'] = 'submission-' + unsignedSubmission.id; + unsignedSubmission.data = data; if (request) { @@ -1930,6 +1932,24 @@ function submissionChecker(submissions) { } } + var cloneUnsignedCredentialsPromise = Promise.resolve(); + if (unsignedSubmission.data && !unsignedSubmission.data['fl-credentials']) { + + var prevSubCred = _.filter(esub, function (submission) { + return submission.data && submission.data['fl-credentials']; + }); + + var previousSubWithCredentials = _.maxBy(prevSubCred, function (el) { + return new Date(el.createdAt).getTime(); + }); + + unsignedSubmission.data['fl-credentials'] = 'submission-' + unsignedSubmission.id; + + if (previousSubWithCredentials) { + cloneUnsignedCredentialsPromise = cloneCredentials(previousSubWithCredentials.data['fl-credentials'], unsignedSubmission, true); + } + } + var usub = _.filter(submissions, function (submission) { return submission.data.submissionType === "unsigned" && submission.platform === "ios"; }); @@ -1946,6 +1966,8 @@ function submissionChecker(submissions) { return cloneAppStoreCredentialsPromise.then(function () { return cloneEnterpriseCredentialsPromise; + }).then(function () { + return cloneUnsignedCredentialsPromise; }).then(function () { if (_.isEmpty(appStoreSubmission)) { return Fliplet.App.Submissions.create({ From 668bc43a9ea8a99ac97cbc56f8a76fd64ac8bb10 Mon Sep 17 00:00:00 2001 From: YaroslavOvdii Date: Tue, 10 Sep 2019 16:10:33 +0300 Subject: [PATCH 173/318] Added line breaks --- js/interface.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/interface.js b/js/interface.js index c0eae5f..4e0dd55 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1588,10 +1588,12 @@ function checkDemoUser() { // We check how many times use google auto-fill after numerous tries found out that google inserts data to this input // only three times at a row, so, therefore, the fourth time it's a user trying to input information from auto-fill. var $demoUserFiled = $('#fl-store-revDemoUser'); + if (!userInput && autoFill < 3) { $demoUserFiled.val(demoUser ? demoUser : ''); autoFill++; } + $('#fl-store-revDemoPass').prop('required', $demoUserFiled.val() !== ''); } From bc85b1ccd238a3242300fdaaff31c6dcdb4bcb90 Mon Sep 17 00:00:00 2001 From: Maksym Date: Tue, 10 Sep 2019 13:57:06 +0300 Subject: [PATCH 174/318] ui changes --- css/interface.css | 6 +- interface.html | 492 ++++++++++++++++++++++++---------------------- js/interface.js | 13 +- 3 files changed, 277 insertions(+), 234 deletions(-) diff --git a/css/interface.css b/css/interface.css index aff4a90..fd8adea 100644 --- a/css/interface.css +++ b/css/interface.css @@ -520,4 +520,8 @@ h3 small { .screenshot-previews .alert { margin-bottom: 0; -} \ No newline at end of file +} + +.analytics-success { + color: rgb(106, 168, 79); +} diff --git a/interface.html b/interface.html index 7a2bdf8..d414934 100644 --- a/interface.html +++ b/interface.html @@ -528,240 +528,9 @@