Merge branch 'develop' into dw2

This commit is contained in:
William Blythe
2019-01-09 09:24:29 +11:00
28 changed files with 327 additions and 192 deletions

View File

@@ -1,2 +0,0 @@
node_modules
npm-debug.log

View File

@@ -1,45 +0,0 @@
worker_processes 1;
user nobody nobody;
error_log /tmp/error.log;
pid /tmp/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
client_body_temp_path /tmp/client_body;
fastcgi_temp_path /tmp/fastcgi_temp;
proxy_temp_path /tmp/proxy_temp;
scgi_temp_path /tmp/scgi_temp;
uwsgi_temp_path /tmp/uwsgi_temp;
access_log /tmp/access.log;
error_log /tmp/error.log;
keepalive_timeout 3000;
server {
listen 80;
listen [::]:80;
index index.html;
server_name localhost;
root /usr/share/nginx/html;
autoindex on;
location ~* \.(?:manifest|appcache|html?|xml|json|css|js|map|jpg|jpeg|gif|png|ico|svg|eot|ttf|woff|woff2)$ {
expires -1;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
access_log off;
}
location / {
try_files $uri $uri/ /index.html =404;
}
}
}

77
.dockerignore Normal file
View File

@@ -0,0 +1,77 @@
node_modules
npm-debug.log
### Node template
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless

View File

@@ -35,7 +35,7 @@
"title": "Coriolis", "title": "Coriolis",
"description": "Coriolis Shipyard for Elite Dangerous", "description": "Coriolis Shipyard for Elite Dangerous",
"repository": "https://github.com/EDCD/coriolis", "repository": "https://github.com/EDCD/coriolis",
"site": "https://coriolis.edcd.io", "site": "https://coriolis.io",
"author": "https://github.com/edcd", "author": "https://github.com/edcd",
"image": "./src/images/logo/192x192.png" "image": "./src/images/logo/192x192.png"
} }
@@ -81,7 +81,7 @@
"title": "Coriolis", "title": "Coriolis",
"description": "Coriolis Shipyard for Elite Dangerous", "description": "Coriolis Shipyard for Elite Dangerous",
"repository": "https://github.com/EDCD/coriolis", "repository": "https://github.com/EDCD/coriolis",
"site": "https://coriolis.edcd.io", "site": "https://coriolis.io",
"author": "https://github.com/edcd", "author": "https://github.com/edcd",
"image": "./src/images/logo/192x192.png" "image": "./src/images/logo/192x192.png"
} }

View File

@@ -6,29 +6,28 @@ WORKDIR /src/app
RUN mkdir -p /src/app/coriolis RUN mkdir -p /src/app/coriolis
RUN mkdir -p /src/app/coriolis-data RUN mkdir -p /src/app/coriolis-data
COPY ./coriolis/ /src/app/coriolis RUN apk add --update git
COPY ./coriolis-data/ /src/app/coriolis-data
RUN apk update COPY . /src/app/coriolis
RUN apk add git
RUN npm i -g npm RUN npm i -g npm
# Set up coriolis-data # Set up coriolis-data
WORKDIR /src/app/coriolis-data WORKDIR /src/app/coriolis-data
RUN git fetch --all RUN git clone https://github.com/EDCD/coriolis-data.git .
RUN git checkout ${BRANCH}
RUN npm install --no-package-lock RUN npm install --no-package-lock
RUN npm start RUN npm start
# Set up coriolis
WORKDIR /src/app/coriolis WORKDIR /src/app/coriolis
RUN git fetch --all
RUN npm install --no-package-lock RUN npm install --no-package-lock
RUN npm run build RUN npm run build
### STAGE 2: Production Environment ### ### STAGE 2: Production Environment ###
FROM nginx:1.13.12-alpine as web FROM fholzer/nginx-brotli as web
COPY coriolis/.docker/nginx.conf /etc/nginx/nginx.conf COPY nginx.conf /etc/nginx/nginx.conf
COPY --from=builder /src/app/coriolis/build /usr/share/nginx/html COPY --from=builder /src/app/coriolis/build /usr/share/nginx/html
WORKDIR /usr/share/nginx/html WORKDIR /usr/share/nginx/html
EXPOSE 80 EXPOSE 80

View File

@@ -1,48 +1,84 @@
worker_processes 2; worker_processes 1;
error_log ./nginx.error.log; user nobody nobody;
worker_rlimit_nofile 8192; error_log /tmp/error.log;
pid nginx.pid; pid /tmp/nginx.pid;
events { events {
worker_connections 1024; worker_connections 1024;
multi_accept on;
} }
http { http {
access_log off; include /etc/nginx/mime.types;
charset UTF-8; default_type application/octet-stream;
sendfile on;
client_body_temp_path /tmp/client_body;
fastcgi_temp_path /tmp/fastcgi_temp;
proxy_temp_path /tmp/proxy_temp;
scgi_temp_path /tmp/scgi_temp;
uwsgi_temp_path /tmp/uwsgi_temp;
access_log /tmp/access.log;
error_log /tmp/error.log;
types { # https://nginx.org/en/docs/http/ngx_http_gzip_module.html
text/html html htm shtml; # Enable gzip compression.
text/css css; # Default: off
text/xml xml rss; gzip off;
image/gif gif;
image/jpeg jpeg jpg;
application/x-javascript js;
text/plain txt;
image/png png;
image/svg+xml svg;
image/x-icon ico;
application/pdf pdf;
text/cache-manifest appcache;
}
gzip on; # Compression level (1-9).
gzip_vary on; # 5 is a perfect compromise between size and CPU usage, offering about
# 75% reduction for most ASCII files (almost identical to level 9).
# Default: 1
gzip_comp_level 5;
# Don't compress anything that's already small and unlikely to shrink much
# if at all (the default is 20 bytes, which is bad as that usually leads to
# larger files after gzipping).
# Default: 20
gzip_min_length 256;
# Compress data even for clients that are connecting to us via proxies,
# identified by the "Via" header (required for CloudFront).
# Default: off
gzip_proxied any; gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
# Tell proxies to cache both the gzipped and regular version of a resource
# whenever the client's Accept-Encoding capabilities header varies;
# Avoids the issue where a non-gzip capable client (which is extremely rare
# today) would display gibberish if their proxy gave them the gzipped version.
# Default: off
gzip_vary on;
# Compress all output labeled with one of the following MIME-types.
# text/html is always compressed by gzip module.
# Default: text/html
gzip_types *;
brotli on;
# brotli_static on;
brotli_types *;
# This should be turned on if you are going to have pre-compressed copies (.gz) of
# static files available. If not it should be left off as it will cause extra I/O
# for the check. It is best if you enable this in a location{} block for
# a specific directory, or on an individual server{} level.
# gzip_static on;
keepalive_timeout 3000;
server { server {
listen 3301; listen 80;
server_name localhost; listen [::]:80;
root ./build/;
index index.html; index index.html;
server_name localhost;
root /usr/share/nginx/html;
autoindex on;
location ~* \.(?:manifest|appcache|html?|xml|json|css|js|map|jpg|jpeg|gif|png|ico|svg|eot|ttf|woff|woff2)$ { location ~* \.(?:manifest|appcache|html?|xml|json|css|js|map|jpg|jpeg|gif|png|ico|svg|eot|ttf|woff|woff2)$ {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
access_log off;
}
location /service-worker.js {
expires -1; expires -1;
add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Credentials true; add_header Access-Control-Allow-Credentials true;
@@ -50,7 +86,6 @@ http {
add_header Access-Control-Allow-Headers 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type'; add_header Access-Control-Allow-Headers 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
access_log off; access_log off;
} }
location / { location / {
try_files $uri $uri/ /index.html =404; try_files $uri $uri/ /index.html =404;
} }

View File

@@ -5,7 +5,7 @@
"type": "git", "type": "git",
"url": "https://github.com/EDCD/coriolis" "url": "https://github.com/EDCD/coriolis"
}, },
"homepage": "https://coriolis.edcd.io", "homepage": "https://coriolis.io",
"bugs": "https://github.com/EDCD/coriolis/issues", "bugs": "https://github.com/EDCD/coriolis/issues",
"private": true, "private": true,
"engine": "node >= 4.8.1", "engine": "node >= 4.8.1",
@@ -120,6 +120,7 @@
"webpack-notifier": "^1.6.0", "webpack-notifier": "^1.6.0",
"workbox-webpack-plugin": "^3.6.1" "workbox-webpack-plugin": "^3.6.1"
}, },
"sideEffects": false,
"dependencies": { "dependencies": {
"@babel/polyfill": "^7.0.0", "@babel/polyfill": "^7.0.0",
"browserify-zlib-next": "^1.0.1", "browserify-zlib-next": "^1.0.1",

View File

@@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Router from './Router'; import Router from './Router';
import { register } from 'register-service-worker' import { register } from 'register-service-worker';
import { EventEmitter } from 'fbemitter'; import { EventEmitter } from 'fbemitter';
import { getLanguage } from './i18n/Language'; import { getLanguage } from './i18n/Language';
import Persist from './stores/Persist'; import Persist from './stores/Persist';
@@ -72,7 +72,7 @@ export default class Coriolis extends React.Component {
route: {}, route: {},
sizeRatio: Persist.getSizeRatio() sizeRatio: Persist.getSizeRatio()
}; };
this._getAnnouncements() this._getAnnouncements();
Router('', (r) => this._setPage(ShipyardPage, r)); Router('', (r) => this._setPage(ShipyardPage, r));
Router('/import?', (r) => this._importBuild(r)); Router('/import?', (r) => this._importBuild(r));
Router('/import/:data', (r) => this._importBuild(r)); Router('/import/:data', (r) => this._importBuild(r));
@@ -105,18 +105,20 @@ export default class Coriolis extends React.Component {
} }
r.params.ship = ship.id; r.params.ship = ship.id;
r.params.code = ship.toString(); r.params.code = ship.toString();
this._setPage(OutfittingPage, r); this._setPage(OutfittingPage, r)
} catch (err) { } catch (err) {
this._onError('Failed to import ship', r.path, 0, 0, err); this._onError('Failed to import ship', r.path, 0, 0, err);
} }
} }
_getAnnouncements() { async _getAnnouncements() {
return request.get('https://orbis.zone/api/announcement') try {
.query({showInCoriolis: true}) const announces = await request.get('https://orbis.zone/api/announcement')
.then(announces => { .query({ showInCoriolis: true });
this.setState({ announcements: announces.body }) this.setState({ announcements: announces.body });
}) } catch (err) {
console.error(err)
}
} }
/** /**
@@ -351,27 +353,27 @@ export default class Coriolis extends React.Component {
const self = this; const self = this;
if (process.env.NODE_ENV === 'production') { if (process.env.NODE_ENV === 'production') {
register('/service-worker.js', { register('/service-worker.js', {
ready (registration) { ready(registration) {
console.log('Service worker is active.') console.log('Service worker is active.');
}, },
registered (registration) { registered(registration) {
console.log('Service worker has been registered.') console.log('Service worker has been registered.');
}, },
cached (registration) { cached(registration) {
console.log('Content has been cached for offline use.') console.log('Content has been cached for offline use.');
}, },
updatefound (registration) { updatefound(registration) {
console.log('New content is downloading.') console.log('New content is downloading.');
}, },
updated (registration) { updated(registration) {
self.setState({ appCacheUpdate: true }); self.setState({ appCacheUpdate: true });
console.log('New content is available; please refresh.') console.log('New content is available; please refresh.');
}, },
offline () { offline() {
console.log('No internet connection found. App is running in offline mode.') console.log('No internet connection found. App is running in offline mode.');
}, },
error (error) { error(error) {
console.error('Error during service worker registration:', error) console.error('Error during service worker registration:', error);
} }
}); });
} }
@@ -395,10 +397,12 @@ export default class Coriolis extends React.Component {
return <div style={{ minHeight: '100%' }} onClick={this._closeMenu} return <div style={{ minHeight: '100%' }} onClick={this._closeMenu}
className={this.state.noTouch ? 'no-touch' : null}> className={this.state.noTouch ? 'no-touch' : null}>
<Header announcements={this.state.announcements} appCacheUpdate={this.state.appCacheUpdate} currentMenu={currentMenu} /> <Header announcements={this.state.announcements} appCacheUpdate={this.state.appCacheUpdate}
<div className="announcement-container">{this.state.announcements.map(a => <Announcement text={a.message}/>)}</div> currentMenu={currentMenu}/>
<div className="announcement-container">{this.state.announcements.map(a => <Announcement
text={a.message}/>)}</div>
{this.state.error ? this.state.error : this.state.page ? React.createElement(this.state.page, { currentMenu }) : {this.state.error ? this.state.error : this.state.page ? React.createElement(this.state.page, { currentMenu }) :
<NotFoundPage />} <NotFoundPage/>}
{this.state.modal} {this.state.modal}
{this.state.tooltip} {this.state.tooltip}
<footer> <footer>
@@ -408,7 +412,8 @@ export default class Coriolis extends React.Component {
<br/> <br/>
<a <a
href={'https://github.com/EDCD/coriolis/compare/edcd:develop@{' + window.CORIOLIS_DATE + '}...edcd:develop'} href={'https://github.com/EDCD/coriolis/compare/edcd:develop@{' + window.CORIOLIS_DATE + '}...edcd:develop'}
target="_blank" rel="noopener noreferrer" title={'Coriolis Commits since' + window.CORIOLIS_DATE}>Commits since last release target="_blank" rel="noopener noreferrer" title={'Coriolis Commits since' + window.CORIOLIS_DATE}>Commits
since last release
({window.CORIOLIS_DATE})</a> ({window.CORIOLIS_DATE})</a>
</div> </div>
</footer> </footer>

View File

@@ -73,7 +73,12 @@ const GRPCAT = {
'gfsb': 'guardian', 'gfsb': 'guardian',
'gmrp': 'guardian', 'gmrp': 'guardian',
'gsc': 'guardian', 'gsc': 'guardian',
'ghrp': 'guardian' 'ghrp': 'guardian',
// Mining
'scl': 'mining',
'pwa': 'mining',
'sdm': 'mining'
}; };
// Order here is the order in which items will be shown in the modules menu // Order here is the order in which items will be shown in the modules menu
const CATEGORIES = { const CATEGORIES = {
@@ -90,7 +95,7 @@ const CATEGORIES = {
'structural reinforcement': ['hr', 'mrp'], 'structural reinforcement': ['hr', 'mrp'],
'dc': ['dc'], 'dc': ['dc'],
// Hardpoints // Hardpoints
'lasers': ['pl', 'ul', 'bl', 'ml'], 'lasers': ['pl', 'ul', 'bl'],
'projectiles': ['mc', 'c', 'fc', 'pa', 'rg'], 'projectiles': ['mc', 'c', 'fc', 'pa', 'rg'],
'ordnance': ['mr', 'tp', 'nl'], 'ordnance': ['mr', 'tp', 'nl'],
// Utilities // Utilities
@@ -102,7 +107,9 @@ const CATEGORIES = {
'experimental': ['axmc', 'axmr', 'rfl', 'tbrfl', 'tbsc', 'tbem', 'xs', 'sfn', 'rcpl', 'dtl', 'rsl', 'mahr',], 'experimental': ['axmc', 'axmr', 'rfl', 'tbrfl', 'tbsc', 'tbem', 'xs', 'sfn', 'rcpl', 'dtl', 'rsl', 'mahr',],
// Guardian // Guardian
'guardian': ['gpp', 'gpd', 'gpc', 'ggc', 'gsrp', 'gfsb', 'ghrp', 'gmrp', 'gsc'] 'guardian': ['gpp', 'gpd', 'gpc', 'ggc', 'gsrp', 'gfsb', 'ghrp', 'gmrp', 'gsc'],
'mining': ['ml', 'scl', 'pwa', 'sdm', 'abl'],
}; };
/** /**
@@ -221,7 +228,16 @@ export default class AvailableModulesMenu extends TranslatedComponent {
} }
list.push(buildGroup(grp, modules[grp])); list.push(buildGroup(grp, modules[grp]));
for (const i of modules[grp]) { for (const i of modules[grp]) {
fuzzy.push({ grp, m: i, name: `${i.class}${i.rating} ${translate(grp)} ${i.mount ? i.mount : ''}` }); let mount = '';
if (i.mount === 'F') {
mount = 'Fixed';
} else if (i.mount === 'G') {
mount = 'Gimballed';
} else if (i.mount === 'T') {
mount = 'Turreted';
}
const fuzz = { grp, m: i, name: `${i.class}${i.rating}${mount ? ' ' + mount : ''} ${translate(grp)}` };
fuzzy.push(fuzz);
} }
} }
} }
@@ -363,10 +379,14 @@ export default class AvailableModulesMenu extends TranslatedComponent {
* mounted module and the hovered modules * mounted module and the hovered modules
*/ */
_showSearch() { _showSearch() {
if (this.props.modules instanceof Array) {
return;
}
return ( return (
<FuzzySearch <FuzzySearch
list={this.state.fuzzy} list={this.state.fuzzy}
keys={['grp', 'name']} keys={['grp', 'name']}
tokenize={true}
className={'input'} className={'input'}
width={'100%'} width={'100%'}
style={{ padding: 0 }} style={{ padding: 0 }}

View File

@@ -126,6 +126,9 @@ export default class HardpointSlot extends Slot {
className={'l'}>{translate('shotspeed')}: {formats.int(m.getShotSpeed())}{u.mps}</div> : null} className={'l'}>{translate('shotspeed')}: {formats.int(m.getShotSpeed())}{u.mps}</div> : null}
{m.getPiercing() ? <div className={'l'}>{translate('piercing')}: {formats.int(m.getPiercing())}</div> : null} {m.getPiercing() ? <div className={'l'}>{translate('piercing')}: {formats.int(m.getPiercing())}</div> : null}
{m.getJitter() ? <div className={'l'}>{translate('jitter')}: {formats.f2(m.getJitter())}°</div> : null} {m.getJitter() ? <div className={'l'}>{translate('jitter')}: {formats.f2(m.getJitter())}°</div> : null}
{m.getScanAngle() ? <div className={'l'}>{translate('scan angle')}: {formats.f2(m.getScanAngle())}°</div> : null}
{m.getScanRange() ? <div className={'l'}>{translate('scan range')}: {formats.int(m.getScanRange())}{u.m}</div> : null}
{m.getMaxAngle() ? <div className={'l'}>{translate('max angle')}: {formats.f2(m.getMaxAngle())}°</div> : null}
{showModuleResistances && m.getExplosiveResistance() ? <div {showModuleResistances && m.getExplosiveResistance() ? <div
className='l'>{translate('explres')}: {formats.pct(m.getExplosiveResistance())}</div> : null} className='l'>{translate('explres')}: {formats.pct(m.getExplosiveResistance())}</div> : null}
{showModuleResistances && m.getKineticResistance() ? <div {showModuleResistances && m.getKineticResistance() ? <div

View File

@@ -132,6 +132,10 @@
"gfsb": "Guardian Frame Shift Drive Booster", "gfsb": "Guardian Frame Shift Drive Booster",
"ghrp": "Guardian Hull Reinforcement Package", "ghrp": "Guardian Hull Reinforcement Package",
"gmrp": "Guardian Module Reinforcement Package", "gmrp": "Guardian Module Reinforcement Package",
"pwa": "Pulse Wave Analyser",
"abl": "Abrasion Blaster",
"scl": "Seismic Charge Launcher",
"sdm": "Sub-Surface Displacement Missile",
"tbsc": "Shock Cannon", "tbsc": "Shock Cannon",
"gsc": "Guardian Shard Cannon", "gsc": "Guardian Shard Cannon",
"psg": "Prismatic Shield Generator", "psg": "Prismatic Shield Generator",
@@ -234,6 +238,7 @@
"rof": "Rate of fire", "rof": "Rate of fire",
"angle": "Scan angle", "angle": "Scan angle",
"scanrate": "Scan rate", "scanrate": "Scan rate",
"proberadius": "Probe Radius",
"scantime": "Scan time", "scantime": "Scan time",
"shield": "Shield", "shield": "Shield",
"armour": "Armour", "armour": "Armour",

View File

@@ -103,7 +103,7 @@ export default class AboutPage extends Page {
patreon.com/coriolis_elite patreon.com/coriolis_elite
</a> </a>
, which will be used to keep Coriolis up to date and the servers , which will be used to keep Coriolis up to date and the servers
running. I also run ads, which are also used for development and hosting. running.
</p> </p>
<form <form
action="https://www.paypal.com/cgi-bin/webscr" action="https://www.paypal.com/cgi-bin/webscr"

View File

@@ -224,9 +224,12 @@ export default class OutfittingPage extends Page {
const control = LZString.decompressFromBase64( const control = LZString.decompressFromBase64(
Utils.fromUrlSafe(parts[4]) Utils.fromUrlSafe(parts[4])
).split('/'); ).split('/');
sys = parseFloat(control[0]) || sys; sys = parseFloat(control[0]);
eng = parseFloat(control[1]) || eng; eng = parseFloat(control[1]);
wep = parseFloat(control[2]) || wep; wep = parseFloat(control[2]);
if (sys + eng + wep > 6) {
sys = eng = wep = 2;
}
boost = control[3] == 1 ? true : false; boost = control[3] == 1 ? true : false;
fuel = parseFloat(control[4]) || fuel; fuel = parseFloat(control[4]) || fuel;
cargo = parseInt(control[5]) || cargo; cargo = parseInt(control[5]) || cargo;

View File

@@ -70,6 +70,13 @@ export default class Page extends React.Component {
document.title = this.state.title || 'Coriolis'; document.title = this.state.title || 'Coriolis';
} }
/**
* Update the window title upon mount
*/
componentDidMount() {
document.title = this.state.title || 'Coriolis';
}
/** /**
* Updates the title upon change * Updates the title upon change
* @param {Object} newProps Incoming properties * @param {Object} newProps Incoming properties

View File

@@ -169,10 +169,9 @@ export default class ShipyardPage extends Page {
* @param {Object} u Localized unit map * @param {Object} u Localized unit map
* @param {Function} fInt Localized integer formatter * @param {Function} fInt Localized integer formatter
* @param {Function} fRound Localized round formatter * @param {Function} fRound Localized round formatter
* @param {Boolean} highlight Should this row be highlighted
* @return {React.Component} Table Row * @return {React.Component} Table Row
*/ */
_shipRowElement(s, translate, u, fInt, fRound, highlight) { _shipRowElement(s, translate, u, fInt, fRound) {
let noTouch = this.context.noTouch; let noTouch = this.context.noTouch;
return ( return (
@@ -181,7 +180,6 @@ export default class ShipyardPage extends Page {
style={{ height: '1.5em' }} style={{ height: '1.5em' }}
className={cn({ className={cn({
highlighted: noTouch && this.state.shipId === s.id, highlighted: noTouch && this.state.shipId === s.id,
alt: highlight
})} })}
onMouseEnter={noTouch && this._highlightShip.bind(this, s.id)} onMouseEnter={noTouch && this._highlightShip.bind(this, s.id)}
> >
@@ -286,27 +284,13 @@ export default class ShipyardPage extends Page {
let shipRows = new Array(shipSummaries.length); let shipRows = new Array(shipSummaries.length);
let detailRows = new Array(shipSummaries.length); let detailRows = new Array(shipSummaries.length);
let lastShipSortValue = null;
let backgroundHighlight = false;
for (let s of shipSummaries) { for (let s of shipSummaries) {
let shipSortValue = s[shipPredicate];
if (shipPredicateIndex != undefined) {
shipSortValue = shipSortValue[shipPredicateIndex];
}
if (shipSortValue != lastShipSortValue) {
backgroundHighlight = !backgroundHighlight;
lastShipSortValue = shipSortValue;
}
detailRows[i] = this._shipRowElement( detailRows[i] = this._shipRowElement(
s, s,
translate, translate,
units, units,
fInt, fInt,
formats.f1, formats.f1,
backgroundHighlight
); );
shipRows[i] = ( shipRows[i] = (
<tr <tr
@@ -314,7 +298,6 @@ export default class ShipyardPage extends Page {
style={{ height: '1.5em' }} style={{ height: '1.5em' }}
className={cn({ className={cn({
highlighted: noTouch && this.state.shipId === s.id, highlighted: noTouch && this.state.shipId === s.id,
alt: backgroundHighlight
})} })}
onMouseEnter={noTouch && this._highlightShip.bind(this, s.id)} onMouseEnter={noTouch && this._highlightShip.bind(this, s.id)}
> >

View File

@@ -94,6 +94,10 @@ export const ModuleGroupToName = {
gsc: 'Guardian Shard Cannon', gsc: 'Guardian Shard Cannon',
tbem: 'Enzyme Missile Rack', tbem: 'Enzyme Missile Rack',
tbrfl: 'Remote Release Flechette Launcher', tbrfl: 'Remote Release Flechette Launcher',
pwa: 'Pulse Wave Analyser',
abl: 'Abrasion Blaster',
scl: 'Seismic Charge Launcher',
sdm: 'Sub-Surface Displacement Missile',
}; };
let GrpNameToCodeMap = {}; let GrpNameToCodeMap = {};

View File

@@ -1073,4 +1073,31 @@ export default class Module {
getHackTime(modified = true) { getHackTime(modified = true) {
return this.get('hacktime', modified); return this.get('hacktime', modified);
} }
/**
* Get the scan range for this module
* @param {Boolean} [modified=true] Whether to take modifications into account
* @return {string} the time for this module
*/
getScanRange(modified = true) {
return this.get('scanrange', modified);
}
/**
* Get the scan angle for this module
* @param {Boolean} [modified=true] Whether to take modifications into account
* @return {string} the time for this module
*/
getScanAngle(modified = true) {
return this.get('scanangle', modified);
}
/**
* Get the max angle for this module
* @param {Boolean} [modified=true] Whether to take modifications into account
* @return {string} the time for this module
*/
getMaxAngle(modified = true) {
return this.get('maxangle', modified);
}
} }

View File

@@ -85,12 +85,12 @@ export function toDetailedBuild(buildName, ship) {
code = ship.toString(); code = ship.toString();
let data = { let data = {
$schema: 'https://coriolis.edcd.io/schemas/ship-loadout/4.json#', $schema: 'https://coriolis.io/schemas/ship-loadout/4.json#',
name: buildName, name: buildName,
ship: ship.name, ship: ship.name,
references: [{ references: [{
name: 'Coriolis.io', name: 'Coriolis.io',
url: 'https://coriolis.edcd.io' + outfitURL(ship.id, code, buildName), url: 'https://coriolis.io' + outfitURL(ship.id, code, buildName),
code, code,
shipId: ship.id shipId: ship.id
}], }],

View File

@@ -78,5 +78,6 @@ export const STATS_FORMATTING = {
'thermres': { 'format': 'pct' }, 'thermres': { 'format': 'pct' },
'wepcap': { 'format': 'round1', 'unit': 'MJ' }, 'wepcap': { 'format': 'round1', 'unit': 'MJ' },
'weprate': { 'format': 'round1', 'unit': 'MW' }, 'weprate': { 'format': 'round1', 'unit': 'MW' },
'jumpboost': { 'format': 'round1', 'unit': 'LY' } 'jumpboost': { 'format': 'round1', 'unit': 'LY' },
'proberadius': { 'format': 'pct1', 'unit': 'pct' },
}; };

View File

@@ -55,7 +55,7 @@ tbody tr {
background-color: @warning-bg; background-color: @warning-bg;
} }
&.alt { &:nth-child(odd){
background-color: @alt-primary-bg; background-color: @alt-primary-bg;
} }
} }

View File

@@ -1,6 +1,6 @@
{ {
"$schema": "http://json-schema.org/draft-04/schema#", "$schema": "http://json-schema.org/draft-04/schema#",
"id": "https://coriolis.edcd.io/schemas/ship-loadout/1.json#", "id": "https://coriolis.io/schemas/ship-loadout/1.json#",
"title": "Ship Loadout", "title": "Ship Loadout",
"type": "object", "type": "object",
"description": "The details for a specific ship build/loadout. DEPRECATED in favor of Version 3", "description": "The details for a specific ship build/loadout. DEPRECATED in favor of Version 3",

View File

@@ -1,6 +1,6 @@
{ {
"$schema": "http://json-schema.org/draft-04/schema#", "$schema": "http://json-schema.org/draft-04/schema#",
"id": "https://coriolis.edcd.io/schemas/ship-loadout/2.json#", "id": "https://coriolis.io/schemas/ship-loadout/2.json#",
"title": "Ship Loadout", "title": "Ship Loadout",
"type": "object", "type": "object",
"description": "The details for a specific ship build/loadout. DEPRECATED in favor of Version 3", "description": "The details for a specific ship build/loadout. DEPRECATED in favor of Version 3",

View File

@@ -1,6 +1,6 @@
{ {
"$schema": "http://json-schema.org/draft-04/schema#", "$schema": "http://json-schema.org/draft-04/schema#",
"id": "https://coriolis.edcd.io/schemas/ship-loadout/3.json#", "id": "https://coriolis.io/schemas/ship-loadout/3.json#",
"title": "Ship Loadout", "title": "Ship Loadout",
"type": "object", "type": "object",
"description": "The details for a specific ship build/loadout", "description": "The details for a specific ship build/loadout",

View File

@@ -1,6 +1,6 @@
{ {
"$schema": "http://json-schema.org/draft-04/schema#", "$schema": "http://json-schema.org/draft-04/schema#",
"id": "https://coriolis.edcd.io/schemas/ship-loadout/4.json#", "id": "https://coriolis.io/schemas/ship-loadout/4.json#",
"title": "Ship Loadout", "title": "Ship Loadout",
"type": "object", "type": "object",
"description": "The details for a specific ship build/loadout", "description": "The details for a specific ship build/loadout",

View File

@@ -8,7 +8,13 @@ if (workbox) {
workbox.routing.registerRoute( workbox.routing.registerRoute(
new RegExp('/(.*?)'), new RegExp('/(.*?)'),
workbox.strategies.staleWhileRevalidate() workbox.strategies.staleWhileRevalidate({
plugins: [
new workbox.cacheableResponse.Plugin({
statuses: [0, 200]
})
]
})
); );
workbox.routing.registerRoute( workbox.routing.registerRoute(

View File

@@ -14,7 +14,7 @@ module.exports = {
}, },
mode: 'development', mode: 'development',
entry: { entry: {
main: './src/app/index.js' main: './src/app/index.js',
}, },
resolve: { resolve: {
// When requiring, you don't need to add these extensions // When requiring, you don't need to add these extensions
@@ -22,13 +22,11 @@ module.exports = {
}, },
optimization: { optimization: {
minimize: false, minimize: false,
splitChunks: { usedExports: true
chunks: 'all'
}
}, },
output: { output: {
path: path.join(__dirname, 'build'), path: path.join(__dirname, 'build'),
filename: 'app.js', chunkFilename: '[name].bundle.js',
publicPath: '/' publicPath: '/'
}, },
plugins: [ plugins: [
@@ -56,7 +54,10 @@ module.exports = {
module: { module: {
rules: [ rules: [
{ test: /\.css$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' }) }, { test: /\.css$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' }) },
{ test: /\.less$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader!less-loader' }) }, {
test: /\.less$/,
loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader!less-loader' })
},
{ test: /\.(js|jsx)$/, loaders: ['babel-loader'], include: path.join(__dirname, 'src') }, { test: /\.(js|jsx)$/, loaders: ['babel-loader'], include: path.join(__dirname, 'src') },
{ test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff' }, { test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff' },
{ test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff' }, { test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff' },

View File

@@ -11,26 +11,28 @@ const buildDate = new Date();
module.exports = { module.exports = {
devtool: 'source-map', devtool: 'source-map',
entry: { entry: {
main: ['./src/app/index.js'] main: './src/app/index.js'
}, },
resolve: { resolve: {
extensions: ['.js', '.jsx', '.json', '.less'] extensions: ['.js', '.jsx', '.json', '.less']
}, },
output: { output: {
path: path.join(__dirname, 'build'), path: path.join(__dirname, 'build'),
filename: '[name].[hash].js', chunkFilename: '[name].bundle.js',
publicPath: '/', publicPath: '/',
globalObject: 'this' globalObject: 'this'
}, },
mode: 'production', mode: 'production',
optimization: { optimization: {
minimize: true, minimize: true,
splitChunks: { usedExports: true
chunks: 'all'
}
}, },
plugins: [ plugins: [
new CopyWebpackPlugin(['src/.htaccess', { from: 'src/schemas', to: 'schemas' }, {from: 'src/images/logo/*', flatten: true, to: ''}, 'src/iframe.html', 'src/xdLocalStoragePostMessageApi.min.js']), new CopyWebpackPlugin(['src/.htaccess', { from: 'src/schemas', to: 'schemas' }, {
from: 'src/images/logo/*',
flatten: true,
to: ''
}, 'src/iframe.html', 'src/xdLocalStoragePostMessageApi.min.js']),
// new webpack.optimize.CommonsChunkPlugin({ // new webpack.optimize.CommonsChunkPlugin({
// name: 'lib', // name: 'lib',
// filename: 'lib.[chunkhash:6].js' // filename: 'lib.[chunkhash:6].js'
@@ -48,15 +50,15 @@ module.exports = {
disable: false, disable: false,
allChunks: true allChunks: true
}), }),
new BugsnagBuildReporterPlugin({ // new BugsnagBuildReporterPlugin({
apiKey: 'ba9fae819372850fb660755341fa6ef5', // apiKey: 'ba9fae819372850fb660755341fa6ef5',
appVersion: `${pkgJson.version}-${buildDate.toISOString()}` // appVersion: `${pkgJson.version}-${buildDate.toISOString()}`
}, { /* opts */ }), // }, { /* opts */ }),
new BugsnagSourceMapUploaderPlugin({ // new BugsnagSourceMapUploaderPlugin({
apiKey: 'ba9fae819372850fb660755341fa6ef5', // apiKey: 'ba9fae819372850fb660755341fa6ef5',
overwrite: true, // overwrite: true,
appVersion: `${pkgJson.version}-${buildDate.toISOString()}` // appVersion: `${pkgJson.version}-${buildDate.toISOString()}`
}), // }),
new InjectManifest({ new InjectManifest({
swSrc: './src/sw.js', swSrc: './src/sw.js',
importWorkboxFrom: 'cdn', importWorkboxFrom: 'cdn',
@@ -66,7 +68,10 @@ module.exports = {
module: { module: {
rules: [ rules: [
{ test: /\.css$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' }) }, { test: /\.css$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' }) },
{ test: /\.less$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader!less-loader' }) }, {
test: /\.less$/,
loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader!less-loader' })
},
{ test: /\.(js|jsx)$/, loader: 'babel-loader?cacheDirectory=true', include: path.join(__dirname, 'src') }, { test: /\.(js|jsx)$/, loader: 'babel-loader?cacheDirectory=true', include: path.join(__dirname, 'src') },
{ test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff' }, { test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff' },
{ test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff' }, { test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff' },