Skip to content

Commit

Permalink
Merge pull request #27838 from code-dot-org/dtp_candidate_66bbbb48
Browse files Browse the repository at this point in the history
DTP (Test > Production: 66bbbb4)
  • Loading branch information
Hamms committed Apr 2, 2019
2 parents d005b3a + ddd5119 commit 29fed28
Show file tree
Hide file tree
Showing 108 changed files with 2,648 additions and 1,253 deletions.
154 changes: 21 additions & 133 deletions apps/src/applab/Exporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,21 @@ import exportExpoAppEjs from '../templates/export/expo/App.js.ejs';
import exportExpoCustomAssetJs from '../templates/export/expo/CustomAsset.exported_js';
import exportExpoDataWarningJs from '../templates/export/expo/DataWarning.exported_js';
import exportExpoMetroConfigJs from '../templates/export/expo/metro.config.exported_js';
import exportExpoPackagedFilesEjs from '../templates/export/expo/packagedFiles.js.ejs';
import exportExpoPackagedFilesEntryEjs from '../templates/export/expo/packagedFilesEntry.js.ejs';
import exportExpoWarningPng from '../templates/export/expo/warning.png';
import exportExpoIconPng from '../templates/export/expo/icon.png';
import exportExpoSplashPng from '../templates/export/expo/splash.png';
import logToCloud from '../logToCloud';
import {getAppOptions} from '@cdo/apps/code-studio/initApp/loadApp';
import project from '@cdo/apps/code-studio/initApp/project';
import {EXPO_SESSION_SECRET} from '../constants';
import {fetchWebpackRuntime} from '../util/exporter';
import {
extractSoundAssets,
createPackageFilesFromZip,
createPackageFilesFromExpoFiles,
rewriteAssetUrls,
getEnvironmentPrefix,
fetchWebpackRuntime
} from '../util/exporter';

// This whitelist determines which appOptions properties
// will get exported with the applab app, appearing in the
Expand Down Expand Up @@ -316,7 +321,8 @@ export default {
appOptionsPath: null,
commonLocalePath: null,
applabLocalePath: null,
commonCssPath: null
commonCssPath: null,
webpackRuntimePath: null
});
} else {
html = exportProjectEjs({
Expand Down Expand Up @@ -539,10 +545,7 @@ export default {
// Write a packagedFiles.js into the zip that contains require
// statements for each file under assets. This will allow the
// Expo app to locally install of these files onto the device.
const packagedFilesJs = this.createPackageFilesFromZip(
zip,
appName
);
const packagedFilesJs = createPackageFilesFromZip(zip, appName);
zip.file(appName + '/packagedFiles.js', packagedFilesJs);
}
return resolve(zip);
Expand Down Expand Up @@ -583,72 +586,6 @@ export default {
});
},

createPackageFilesFromZip(zip, appName) {
const moduleList = [];
zip.folder(appName + '/assets').forEach((fileName, file) => {
if (!file.dir) {
moduleList.push({fileName});
}
});
const entries = moduleList.map(module =>
exportExpoPackagedFilesEntryEjs({module})
);
return exportExpoPackagedFilesEjs({entries});
},

createPackageFilesFromExpoFiles(files) {
const moduleList = [];
const assetPrefix = 'assets/';
const assetPrefixLength = assetPrefix.length;
for (const fileName in files) {
if (fileName.indexOf(assetPrefix) !== 0) {
continue;
}
const relativePath = fileName.substring(assetPrefixLength);
moduleList.push({fileName: relativePath});
}
const entries = moduleList.map(module =>
exportExpoPackagedFilesEntryEjs({module})
);
return exportExpoPackagedFilesEjs({entries});
},

async generateExpoApk(options, config) {
const {appName, expoSnackId, iconUri, splashImageUri} = options;
const session = new SnackSession({
sessionId: `${getEnvironmentPrefix()}-${project.getCurrentId()}`,
name: `project-${project.getCurrentId()}`,
sdkVersion: '31.0.0',
snackId: expoSnackId,
user: {
sessionSecret: config.expoSession || EXPO_SESSION_SECRET
}
});

const appJson = JSON.parse(
exportExpoAppJsonEjs({
appName,
projectId: project.getCurrentId(),
iconPath: iconUri,
splashImagePath: splashImageUri
})
);

// TODO: remove the onlineOnlyExpo patching once getApkUrlAsync()
// properly supports our full app.json
const {
updates, // eslint-disable-line no-unused-vars
assetBundlePatterns, // eslint-disable-line no-unused-vars
packagerOpts, // eslint-disable-line no-unused-vars
...onlineOnlyExpo
} = appJson.expo;
appJson.expo = onlineOnlyExpo;

const artifactUrl = await session.getApkUrlAsync(appJson);

return artifactUrl;
},

async publishToExpo(appName, code, levelHtml, config) {
const {css, outerHTML} = transformLevelHtml(levelHtml);
const fontAwesomeCSS = exportFontAwesomeCssEjs({
Expand All @@ -657,6 +594,10 @@ export default {
const exportConfig = await getExportConfig(true);
const appOptionsJs = getAppOptionsFile(true, exportConfig.channelId);
const {origin} = window.location;
const webpackRuntimePath =
getEnvironmentPrefix() === 'cdo-development'
? `${origin}/blockly/js/webpack-runtime.js`
: `${origin}/blockly/js/webpack-runtime.min.js`;
const applabApiPath =
getEnvironmentPrefix() === 'cdo-development'
? `${origin}/blockly/js/applab-api.js`
Expand All @@ -670,6 +611,7 @@ export default {
appOptionsPath: 'appOptions.j',
fontPath: fontAwesomeWOFFPath,
applabApiPath,
webpackRuntimePath,
jQueryPath: 'https://code.jquery.com/jquery-1.12.1.min.js',
commonCssPath: `${origin}/blockly/css/common.css`,
applabCssPath: `${origin}/blockly/css/applab.css`
Expand Down Expand Up @@ -768,7 +710,7 @@ export default {
};
});
files['packagedFiles.js'] = {
contents: this.createPackageFilesFromExpoFiles(files),
contents: createPackageFilesFromExpoFiles(files),
type: 'CODE'
};

Expand Down Expand Up @@ -802,45 +744,15 @@ function generateAppAssets(params) {
filename: asset.filename
}));

const soundRegex = /(\bsound:\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi;
const allSounds = [
...(html.match(soundRegex) || []),
...(code.match(soundRegex) || [])
];
const uniqueSounds = [...new Set(allSounds)];
const soundAssets = uniqueSounds.map(soundProtocolUrl => {
const soundOriginUrl = assetPrefix.fixPath(soundProtocolUrl);
const filename = soundProtocolUrl.replace(assetPrefix.SOUND_PREFIX, '');
return {
url: soundOriginUrl,
rootRelativePath: rootRelativeAssetPrefix + filename,
zipPath: zipAssetPrefix + filename,
dataType: 'binary',
filename,
searchUrl: soundProtocolUrl
};
const soundAssets = extractSoundAssets({
sources: [html, code],
rootRelativeAssetPrefix,
zipAssetPrefix
});

return [...appAssets, ...soundAssets];
}

// TODO: for expoMode, replace spaces in asset filenames or wait for this fix
// to make it into Metro Bundler:
// https://github.com/facebook/react-native/pull/10365
function rewriteAssetUrls(appAssets, data) {
return appAssets.reduce(function(data, assetToDownload) {
const searchUrl = assetToDownload.searchUrl || assetToDownload.filename;
data = data.replace(
new RegExp(`["|']${assetToDownload.url}["|']`, 'g'),
`"${assetToDownload.rootRelativePath}"`
);
return data.replace(
new RegExp(`["|']${searchUrl}["|']`, 'g'),
`"${assetToDownload.rootRelativePath}"`
);
}, data);
}

function transformLevelHtml(levelHtml) {
const holder = document.createElement('div');
holder.innerHTML = levelHtml;
Expand All @@ -859,27 +771,3 @@ function transformLevelHtml(levelHtml) {
css
};
}

function getEnvironmentPrefix() {
const {hostname} = window.location;
if (hostname.includes('adhoc')) {
// As adhoc hostnames may include other keywords, check it first.
return 'cdo-adhoc';
}
if (hostname.includes('test')) {
return 'cdo-test';
}
if (hostname.includes('levelbuilder')) {
return 'cdo-levelbuilder';
}
if (hostname.includes('staging')) {
return 'cdo-staging';
}
if (hostname.includes('localhost')) {
return 'cdo-development';
}
if (hostname.includes('code.org')) {
return 'cdo';
}
return 'cdo-unknown';
}
3 changes: 2 additions & 1 deletion apps/src/applab/applab.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ import experiments from '../util/experiments';
import header from '../code-studio/header';
import {TestResults, ResultType} from '../constants';
import i18n from '../code-studio/i18n';
import {generateExpoApk} from '../util/exporter';

/**
* Create a namespace for the application.
Expand Down Expand Up @@ -832,7 +833,7 @@ Applab.exportApp = function(expoOpts) {

const {mode, expoSnackId, iconUri, splashImageUri} = expoOpts || {};
if (mode === 'expoGenerateApk') {
return Exporter.generateExpoApk(
return generateExpoApk(
{
appName,
expoSnackId,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import PropTypes from 'prop-types';
import React from 'react';
import {connect} from 'react-redux';
import {Table} from 'react-bootstrap';
import _ from 'lodash';
import {COURSE_CSF} from '../../workshopConstants';
import {
PermissionPropType,
WorkshopAdmin,
ProgramManager,
Organizer
} from '../../permission';

const questionOrder = {
facilitator_effectiveness: [
Expand All @@ -24,14 +31,15 @@ const questionOrder = {
]
};

export default class FacilitatorAveragesTable extends React.Component {
export class FacilitatorAveragesTable extends React.Component {
static propTypes = {
facilitatorAverages: PropTypes.object.isRequired,
facilitatorId: PropTypes.number.isRequired,
facilitatorName: PropTypes.string.isRequired,
questions: PropTypes.object.isRequired,
courseName: PropTypes.string.isRequired,
facilitatorResponseCounts: PropTypes.object.isRequired
facilitatorResponseCounts: PropTypes.object.isRequired,
permission: PermissionPropType.isRequired
};

constructor(props) {
Expand All @@ -44,6 +52,26 @@ export default class FacilitatorAveragesTable extends React.Component {
};
}

relatedWorkshopDescriptor(possessiveName) {
if (this.props.permission.has(WorkshopAdmin)) {
return `${possessiveName} average for this workshop`;
} else if (this.props.permission.has(ProgramManager)) {
return `Average for all your regional partner's ${
this.props.courseName
} workshops since June 2018`;
} else if (this.props.permission.has(Organizer)) {
return `${possessiveName} average for all ${
this.props.courseName
} workshops
organized since June 2018`;
} else {
return `${possessiveName} average for all ${
this.props.courseName
} workshops
facilitated since June 2018`;
}
}

renderAverage(displayNumber, category) {
if (displayNumber) {
return `${displayNumber.toFixed(2)} / ${
Expand All @@ -65,10 +93,7 @@ export default class FacilitatorAveragesTable extends React.Component {
<tr>
<th />
<th>{possessiveName} average for this workshop</th>
<th>
{possessiveName} average for all {this.props.courseName} workshops
since June 2018
</th>
<th>{this.relatedWorkshopDescriptor(possessiveName)}</th>
</tr>
</thead>
<tbody>
Expand Down Expand Up @@ -140,3 +165,7 @@ export default class FacilitatorAveragesTable extends React.Component {
);
}
}

export default connect(state => ({
permission: state.workshopDashboard.permission
}))(FacilitatorAveragesTable);
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import FacilitatorAveragesTable from './facilitator_averages_table';
import {FacilitatorAveragesTable} from './facilitator_averages_table';
import Permission from '../../permission';
import reactBootstrapStoryDecorator from '../../../reactBootstrapStoryDecorator';

export default storybook => {
Expand Down Expand Up @@ -123,6 +124,7 @@ export default storybook => {
all_my_workshops: {1: 200}
}}
facilitatorId={1}
permission={new Permission(['facilitator'])}
/>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const DEEP_DIVE = 'Deep Dive';
const NA = 'N/A';
const LOCAL_SUMMER = '5-day Summer';

class WorkshopEnrollmentSchoolInfo extends React.Component {
export class WorkshopEnrollmentSchoolInfo extends React.Component {
constructor(props) {
super(props);

Expand Down

0 comments on commit 29fed28

Please sign in to comment.