diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 7c83727209..0000000000 --- a/Dockerfile +++ /dev/null @@ -1,28 +0,0 @@ -FROM bagel/universe:dc9b2190001e9c64d7b5e63dbf9999b2e4c83d25 - -# Source -COPY ./app /opt/hub/app -# Webpack -COPY ./webpack.config.js /opt/hub/webpack.config.js -COPY ./_webpack /opt/hub/_webpack -# Make -COPY ./Makefile /opt/hub/Makefile -# Gulp -COPY ./gulpfile.js /opt/hub/gulpfile.js -COPY ./gulp-tasks /opt/hub/gulp-tasks -# ESLint -COPY ./.eslintrc /opt/hub/.eslintrc -# Flow -ENV LOGNAME bagels -COPY ./flow-libs /opt/hub/flow-libs -COPY .flowconfig /opt/hub/.flowconfig -ENV PATH /opt/flow/:$PATH - -RUN DEBUG=* webpack -d -RUN make server-target -RUN make styles-base -RUN gulp images::dev -RUN make images -RUN make docker-font-dev -# favicon -COPY ./app/favicon.ico /opt/hub/app/.build/ diff --git a/Jenkinsfile b/Jenkinsfile deleted file mode 100644 index fa29520b5f..0000000000 --- a/Jenkinsfile +++ /dev/null @@ -1,8 +0,0 @@ -// Only run on Linux atm -wrappedNode(label: 'docker') { - deleteDir() - stage "checkout" - checkout scm - - documentationChecker("docs") -} diff --git a/Makefile b/Makefile deleted file mode 100644 index ccc714aa21..0000000000 --- a/Makefile +++ /dev/null @@ -1,101 +0,0 @@ -.PHONY: dns server-prod-target server-target server-extras base base-tag prod prod-tag push-builders js-prod images images-prod - -# Set up make's -dns: - ./containers/dnsmasq/configure_system_dns.sh -hub-deps: - git clone git@github.com:docker/docker-ux.git ./private-deps/docker-ux - git clone git@github.com:docker/hub-js-sdk.git ./private-deps/hub-js-sdk -# -> bootstrap-dev -server-target: - mkdir -p app/.build/public/styles - cp -R app/img app/.build/public -styles-base: - cp ./private-deps/docker-ux/dist/styles/main.css ./app/.build/public/styles/main.css -images: - cp -R ./private-deps/docker-ux/dist/images ./app/.build/public/ -docker-font-dev: - cp -R ./private-deps/docker-ux/dist/fonts ./app/.build/public/ - cp ./app/fonts/* ./app/.build/public/fonts/ - mkdir -p app/.build/public/styles - cp ./app/styles/font-awesome.min.css ./app/.build/public/styles/font-awesome.min.css - -# Circle make's -dev: - docker build -t bagel/hub-builders-dev . -dev-tag: - $(shell docker tag bagel/hub-builders-dev:latest bagel/hub-builders-dev:$(shell git rev-parse --verify HEAD)) -local: - docker build -f local.Dockerfile -t bagel/hub-builders-local . -copy-local: - docker run --name bagel-local -d bagel/hub-builders-local sleep 50s - docker cp bagel-local:/opt/hub/.build-prod ./.local/ -stage: - docker build -f dockerfiles/Dockerfile-stage-build -t bagel/hub-builders-stage . -copy-stage: - docker run --name bagel-stage -d bagel/hub-builders-stage sleep 50s - docker cp bagel-stage:/opt/hub/.build-prod ./.stage/ -prod: - docker build -f dockerfiles/Dockerfile-prod-build -t bagel/hub-builders-prod . -base-prod-tag: - $(shell docker tag bagel/hub-builders-prod:latest bagel/hub-builders-prod:$(shell git rev-parse --verify HEAD)) -copy-prod: - docker run --name bagel-prod -d bagel/hub-builders-prod sleep 50s - docker cp bagel-prod:/opt/hub/.build-prod . - -# Dockerfile make's -server-prod-target: - rm -rf .build-prod - mkdir -p .build-prod -server-extras: - cp app-server/package.json .build-prod/package.json - cp app-server/favicons/favicon-dev.ico .build-prod/favicon.ico - cp app-server/Dockerfile .build-prod/Dockerfile -js-prod: - ENV=production webpack --production --config _webpack/webpack.prod.config.js - ENV=production webpack --production --config _webpack/webpack.server.config.js -js-stage: - ENV=staging webpack --production --config _webpack/webpack.prod.config.js - ENV=staging webpack --production --config _webpack/webpack.server.config.js -js-local: - ENV=local webpack --production --config _webpack/webpack.prod.config.js - ENV=local webpack --production --config _webpack/webpack.server.config.js -images-prod: - cp -R ./private-deps/docker-ux/dist/images .build-prod/public/ -docker-font-prod: - cp -R ./private-deps/docker-ux/dist/fonts .build-prod/public - cp -R ./app/fonts/* .build-prod/public/fonts/ - mkdir -p app/.build-prod/public/styles - cp ./app/styles/font-awesome.min.css .build-prod/public/styles/font-awesome.min.css -styles-base-prod: - cp ./private-deps/docker-ux/dist/styles/main.css .build-prod/public/styles/main.css -stats-dir: - mkdir -p /stats/css -css-stats: - /opt/hub/node_modules/.bin/cssstats file /opt/hub/.build-prod/public/styles/$(shell cat /tmp/.client-js-hash) > /stats/css-stats.json - -# Unused make commands -# Universe commands are no longer used as we now have the universe branch -dev-test-jest: - docker build -f dockerfiles/Dockerfile-builders-dev-jest -t bagel/hub-builders-dev-jest . -push-builders: - docker push bagel/hub-builders-prod - docker push bagel/hub-builders-dev -prod-tag: - $(shell docker tag bagel/hub-prod:latest bagel/hub-prod:$(shell git rev-parse --verify HEAD)) -universe: -# [ ! "${$(npm -v):0:1}" == "2" ] && echo "please \"npm install -g npm\" to get npm3'" && exit 1 - rm -rf node_modules - npm install --production - docker build -f dockerfiles/milky-way -t bagel/milky-way . - docker build -f dockerfiles/universe -t bagel/universe . -push-universe: - $(shell docker tag bagel/milky-way:latest bagel/milky-way:$(shell git rev-parse --verify HEAD)) - $(shell docker tag bagel/universe:latest bagel/universe:$(shell git rev-parse --verify HEAD)) - docker push bagel/milky-way - docker push bagel/universe -new-universe: - sed -i '.bak' "s/universe:[a-z0-9]*$$/universe:${UNIVERSE_TAG}/" Dockerfile - sed -i '.bak' "s/universe:[a-z0-9]*$$/universe:${UNIVERSE_TAG}/" local.Dockerfile - sed -i '.bak' "s/universe:[a-z0-9]*$$/universe:${UNIVERSE_TAG}/" dockerfiles/* - sed -i '.bak' "s/milky-way:[a-z0-9]*$$/milky-way:${UNIVERSE_TAG}/" dockerfiles/* diff --git a/README.md b/README.md deleted file mode 100644 index 50a2ce98bb..0000000000 --- a/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# Quickstart - -*Make sure to clone this repo into your `/Users/` directory for it to run correctly* - -```bash -make dns -make hub-deps -# you must log in as the 'dux' user. ask one of the frontend -# team members for credentials -npm login -npm install -docker-compose build -npm run build:dev -./startup-scripts/bootstrap-dev.sh -docker-compose up -d -``` - -At this point you will need `tmux` to run `boot-dev-tmux.sh`, it can -be installed on OSX by `brew install tmux` - -```bash -./startup-scripts/boot-dev-tmux.sh -``` - -## tmux env - -Here are some basic commands to help you get around tmux. `C` is -Control, `-` means hit both keys, everything else it a literal -character you need to produce. - -| Command | Keys | -|--------------|---------| -| Next Window | C-b n | -| Next Panel | C-b o | -| Close Window | C-b & y | - -# Docs - -* [React](docs/concepts/React.md) -* [Flux](docs/concepts/Flux.md) -* [React Native](docs/concepts/React-Native.md) -* [React Router](docs/concepts/React-Router.md) -* [Immutability](docs/concepts/Immutability.md) diff --git a/_webpack/_common.webpack.config b/_webpack/_common.webpack.config deleted file mode 100644 index bf58cb7d55..0000000000 --- a/_webpack/_common.webpack.config +++ /dev/null @@ -1,105 +0,0 @@ -var ExtractTextPlugin = require("extract-text-webpack-plugin"); -var debug = require('debug')('webpack--common'); -var fs = require('fs'); -var merge = require('lodash/object/merge'); -var cssstats = require('postcss-cssstats'); -var loaders = require('./_commonLoaders'); - -/* Dux Button Config */ -var elementButton = require('@dux/element-button/defaults'); -var buttons = elementButton.mkButtons([{ - name: 'primary', - color: '#FFF', - bg: '#22B8EB' -},{ - name: 'secondary', - color: '#FFF', - bg: '#232C37' -},{ - name: 'coral', - color: '#FFF', - bg: '#FF85AF' -},{ - name: 'success', - color: '#FFF', - bg: '#0FD85A' -},{ - name: 'warning', - color: '#FFF', - bg: '#FF8546' -},{ - name: 'yellow', - color: '#FFF', - bg: '#FFDE50' -},{ - name: 'alert', - color: '#FFF', - bg: '#EB3E46' -}]); -/** - * cssnaneOpts can be true or an options object - * - * http://cssnano.co/options/ - */ -var cssnanoOpts = { - mergeIdents: false -}; -const defaults = merge(require('@dux/element-card/defaults')({ - capBackground: '#f1f6fb', - borderColor: '#c4cdda' - }), - { - duxElementButton: { - radius: '.25rem', - buttons: buttons - } - }); -module.exports = { - resolve: { - extensions: ['', '.js', '.jsx', '.json'], - root: [ - '/opt/hub/app/scripts/', - '/opt/hub/app/scripts/components' - ] - }, - module: { - preLoaders: loaders.preLoaders, - loaders: loaders.commonLoaders - }, - postcss: [ - require('postcss-import')(), - require('postcss-constants')({ - defaults: defaults - }), - require('postcss-each'), - require('postcss-cssnext')({ - browsers: 'last 2 versions', - features: { - // https://github.com/robwierzbowski/node-pixrem/issues/40 - rem: false - } - }), - require('postcss-nested'), - require('lost')({ - gutter: '1.25rem', - flexbox: 'flex' - }), - require('postcss-cssstats')(function(stats) { - /** - * this cssstats callback runs for every postcss file - * perhaps we want to write out this object and - * record the values over time? - * - * problem: there is no filename here - */ - debug(stats); - }), - require('postcss-url')(), - require('cssnano')(cssnanoOpts) - ], - eslint: { - failOnError: true - }, - bail: true, - profile: true -} diff --git a/_webpack/_commonLoaders.js b/_webpack/_commonLoaders.js deleted file mode 100644 index cd4a46ed51..0000000000 --- a/_webpack/_commonLoaders.js +++ /dev/null @@ -1,22 +0,0 @@ -var ExtractTextPlugin = require("extract-text-webpack-plugin"); - -var babelcfg = 'babel?optional[]=runtime&stage=0'; - -var preLoaders = [ - { test: /\.jsx?$/, exclude: /node_modules/, loader: 'eslint'} -] - -var commonLoaders = [ - // This loader matches .js and .jsx files - { test: /\.json$/, loader: 'json' }, - { test: /\.jsx?$/, exclude: /node_modules/, loader: babelcfg}, - { test: /dux.*\.jsx?$/, loader: babelcfg}, - { test: /hub-js-sdk.*\.jsx?$/, exclude: /hub-js-sdk.*node_modules.*\.jsx?$/, loader: babelcfg }, - { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss-loader') }, - { test: /\.svg$/, loader: 'svg-inline' } -] - -module.exports = { - preLoaders: preLoaders, - commonLoaders: commonLoaders -} diff --git a/_webpack/_envConfig.js b/_webpack/_envConfig.js deleted file mode 100644 index 69b6ded1a3..0000000000 --- a/_webpack/_envConfig.js +++ /dev/null @@ -1,104 +0,0 @@ -var webpack = require('webpack'); -var debug = require('debug')('_envConfig'); - -debug(process.env.ENV); - -function isProd() { - return process.env.ENV === 'production'; -} - -/** - * `development` is staging. - * `staging` is also staging. - * - * The keys in these objects are possible ENV configurations - * - * Pointing production to staging during Alpha - */ - -var HUB_URLS = { - local: 'https://hub.dev.docker.com', - development: 'https://hub-stage.docker.com', - staging: 'https://hub-stage.docker.com', - production: 'https://hub.docker.com' -} - -var RECURLY_PUBLIC_KEY = { - local: 'sjc-9XwqFDBZALFs9BP9dn3J8e', - development: 'sjc-9XwqFDBZALFs9BP9dn3J8e', - production: 'sjc-JIfmXVz2OVkg3xg10NhWm1' -} - -// NO LONGER USED -// var MUNCHKIN_CODE = { -// staging: '453-IHP-147', -// production: '929-FJL-178' -// } - -var BUGSNAG_API_KEY = { - staging: 'ec43d0373895ee5eb76ec75301157a85', - production: 'd639ea00dd6e493b739de27a7ee0f90c' -} - -var TUTUM_SIGNIN_URLS = { - development: 'https://dashboard-staging.tutum.co/login/docker/', - production: 'https://dashboard.tutum.co/login/docker/' -} - -var COOKIE_DOMAIN = { - local: 'hub.dev.docker.com', - development: 'bagels.docker.com', - staging: 'hub-stage.docker.com', - production: 'hub.docker.com' -}; - -// NODE_ENV is an express thing but is NOT being used by us -if (isProd() || process.env.ENV === 'staging') { - process.env.NODE_ENV = 'production' -} - -if ( !~['development', 'local', 'staging', 'production'].indexOf(process.env.ENV) ) { - process.env.ENV = 'development'; -} - -// Override some ENV vars -process.env.HUB_API_BASE_URL = process.env.HUB_API_BASE_URL || HUB_URLS[process.env.ENV] || 'https://hub-stage.docker.com'; -process.env.REGISTRY_API_BASE_URL = HUB_URLS[process.env.ENV] || 'https://hub-stage.docker.com'; -process.env.RECURLY_PUBLIC_KEY = RECURLY_PUBLIC_KEY[process.env.ENV] || 'sjc-9XwqFDBZALFs9BP9dn3J8e'; - - -process.env.CLIENT_JS_FILENAME = process.env.CLIENT_JS_FILENAME || 'client.js'; -process.env.CSS_FILENAME = process.env.CSS_FILENAME || 'style.css'; -process.env.COOKIE_DOMAIN = COOKIE_DOMAIN[process.env.ENV] || 'bagels.docker.com'; - -process.env.BOT_TRACKING_ID = 'PXbPb4C2uT'; - -if(isProd()) { - process.env.BUGSNAG_API_KEY = BUGSNAG_API_KEY.production; - process.env.GOOGLE_TAG_MANAGER = 'gtmActive'; - process.env.BOT_TRACKING_ID = 'PXPmP8ILuI'; -} else if(process.env.ENV === 'staging') { - process.env.BUGSNAG_API_KEY = BUGSNAG_API_KEY.staging; - process.env.GOOGLE_TAG_MANAGER = 'gtmDisabled'; -} - -process.env.TUTUM_SIGNIN_URL = TUTUM_SIGNIN_URLS[process.env.ENV] || 'https://dashboard-staging.tutum.co/login/docker/'; - -process.env.NAUTILUS_API_BASE_URL = HUB_URLS[process.env.ENV] + '/api/nautilus/v1'; - -debug(process.env); - -module.exports = new webpack.EnvironmentPlugin([ - 'BUGSNAG_API_KEY', - 'CLIENT_JS_FILENAME', - 'CSS_FILENAME', - 'ENV', - 'NODE_ENV', - 'GOOGLE_TAG_MANAGER', - 'BOT_TRACKING_ID', - 'HUB_API_BASE_URL', - 'NAUTILUS_API_BASE_URL', - 'RECURLY_PUBLIC_KEY', - 'REGISTRY_API_BASE_URL', - 'TUTUM_SIGNIN_URL' -]); diff --git a/_webpack/hashAndReplaceClient.js b/_webpack/hashAndReplaceClient.js deleted file mode 100644 index 837e0b3a88..0000000000 --- a/_webpack/hashAndReplaceClient.js +++ /dev/null @@ -1,37 +0,0 @@ -var fs = require('fs'); -var assert = require('assert'); -/** - * Writes the stats object out to /stats.json so we can fetch it from - * the appropriate container. - * - * This fails hard (throws an AssertionError) if the filename does - * not match the regex. This is good because we don't want it shipping - * to production if we can't reliably find the hash for client.js. - * - * The `CLIENT_JS_REGEX` should match `output.filename` in the webpack - * config below. - */ -module.exports = function() { - var CLIENT_JS_REGEX = /client..*.js$/; - this.plugin('done', function(stats) { - var filename = stats.toJson().assets[0].name; - - console.log(filename); - console.log(stats.toJson().assets[0]); - // write stats object - fs.writeFileSync( - '/tmp/dux-stats-client-js.json', - JSON.stringify(stats.toJson())); - - // test `filename` - assert.strictEqual(true, !!filename.match(CLIENT_JS_REGEX), filename + ' does not match expected client.js regex') - - /** - * Store the client.js hash in /tmp/.clientjs-hash for use - * in the server build process - */ - fs.writeFile('/tmp/.client-js-hash', filename, 'utf8', function(err) { - if (err) throw err; - }); - }); -} \ No newline at end of file diff --git a/_webpack/webpack.prod.config.js b/_webpack/webpack.prod.config.js deleted file mode 100644 index c377284c22..0000000000 --- a/_webpack/webpack.prod.config.js +++ /dev/null @@ -1,32 +0,0 @@ -var ExtractTextPlugin = require("extract-text-webpack-plugin"); -var ENV_CONFIG = require('./_envConfig.js'); -var HASH_CLIENT = require('./hashAndReplaceClient'); -var _ = require('lodash'); -var commonConfig = require('./_common.webpack.config'); -var webpack = require('webpack'); -var debug = require('debug')('webpack--client'); - -var clientConfig = { - entry: '/opt/hub/app/scripts/client.js', - devtool: 'source-map', - output: { - path: '.build-prod/public/', - filename: 'js/client.[hash].js' - }, - plugins: [ - ENV_CONFIG, - new webpack.optimize.DedupePlugin(), - new webpack.optimize.UglifyJsPlugin({ - compress: { - warnings: false - } - }), - new ExtractTextPlugin('styles/[name]-[id]-[hash].css', { allChunks: true }), - HASH_CLIENT - ] -}; -var clientBundle = _.assign({}, commonConfig, clientConfig); - -module.exports = [ - clientBundle -]; diff --git a/_webpack/webpack.server.config.js b/_webpack/webpack.server.config.js deleted file mode 100644 index 0214170503..0000000000 --- a/_webpack/webpack.server.config.js +++ /dev/null @@ -1,54 +0,0 @@ -var assert = require('assert'); -var ExtractTextPlugin = require("extract-text-webpack-plugin"); -var ENV_CONFIG = require('./_envConfig.js'); -var _ = require('lodash'); -var commonConfig = require('./_common.webpack.config'); -var debug = require('debug')('webpack--server'); -var fs = require('fs'); - -process.env.CLIENT_JS_FILENAME = fs.readFileSync('/tmp/.client-js-hash', 'utf-8').split('js/')[1]; -var CSS_FILENAME = _.filter(fs.readdirSync('/opt/hub/.build-prod/public/styles/'), - function(str) { - return !/.*\.map$/.test(str); - }); - -assert.strictEqual(1, CSS_FILENAME.length, CSS_FILENAME); -process.env.CSS_FILENAME = CSS_FILENAME[0]; -fs.writeFileSync('/tmp/.client-js-hash', CSS_FILENAME); - -/** - * blacklist this array from being included in `externals`. - * - * This has the effect of making any modules in this list be - * resolved at build time instead of runtime. This affects the - * server bundle - */ -var blacklist = ['.bin', 'hub-js-sdk', 'dux']; -var node_modules = fs.readdirSync('node_modules').filter(function(x) { - return !_.includes(blacklist, x); -}); - -debug('modules that will be runtime require dependencies of the server: ', node_modules); - - -var serverConfig = { - entry: '/opt/hub/app/scripts/server.js', - output: { - path: '.build-prod/', - filename: 'server.js', - libraryTarget: 'commonjs2' - }, - plugins: [ - ENV_CONFIG, - new ExtractTextPlugin('/.ignore/whatever.css', { - allChunks: true - }) - ], - target: 'node', - externals: node_modules, - node: { - __dirname: '/opt/hub/' - } -}; - -module.exports = _.assign({}, commonConfig, serverConfig); diff --git a/app-server/Dockerfile b/app-server/Dockerfile deleted file mode 100644 index 74d2fdc0a0..0000000000 --- a/app-server/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM bagel/node-alpine:4.1.2 - -WORKDIR /opt/hub - -COPY ./package.json package.json -ADD ./modules.tar /opt/hub/ -COPY ./server.js /opt/hub/ -COPY ./public /opt/hub/public/ -COPY favicon.ico /opt/hub/favicon.ico - -CMD ["node", "--max-old-space-size=2048", "server.js"] diff --git a/app-server/favicons/fav copy.png b/app-server/favicons/fav copy.png deleted file mode 100644 index 7b36ba7a6e..0000000000 Binary files a/app-server/favicons/fav copy.png and /dev/null differ diff --git a/app-server/favicons/favicon-dev.ico b/app-server/favicons/favicon-dev.ico deleted file mode 100644 index f4766ac404..0000000000 Binary files a/app-server/favicons/favicon-dev.ico and /dev/null differ diff --git a/app-server/favicons/favicon.ico b/app-server/favicons/favicon.ico deleted file mode 100644 index 7b36ba7a6e..0000000000 Binary files a/app-server/favicons/favicon.ico and /dev/null differ diff --git a/app-server/package.json b/app-server/package.json deleted file mode 100644 index 2049a85b85..0000000000 --- a/app-server/package.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "name": "docker-hub", - "version": "0.0.1", - "private": true, - "scripts": { - "test": "gulp test", - "start": "node --harmony server/server.js" - }, - "dependencies": { - "@dux/element-card": "0.0.4", - "@dux/element-markdown": "0.0.3", - "@dux/element-button": "0.0.3", - "MD5": "^1.2.1", - "async": "^1.3.0", - "babel": "^5.0.12", - "babel-runtime": "^5.6.18", - "body-parser": "^1.12.2", - "classnames": "^2.1.2", - "cookie": "^0.1.2", - "cookie-parser": "^1.3.4", - "csurf": "^1.8.0", - "debug": "^2.1.3", - "dux": "file:../docker-ux", - "express": "^4.12.3", - "express-state": "^1.2.0", - "flux-router-component": "^0.6.1", - "fluxible": "^0.4.3", - "fluxible-plugin-fetchr": "^0.2.3", - "fluxible-plugin-routr": "^0.3.0", - "highlight.js": "^8.5.0", - "hub-js-sdk": "file:../hub-js-sdk", - "keymirror": "^0.1.1", - "lodash": "^3.6.0", - "marked": "^0.3.3", - "moment": "^2.10.3", - "newrelic": "christopherbiscardi/node-newrelic#c4ccca3764acafaf9c5899e4a1abece828e1f7b8", - "node-jsx": "^0.12.4", - "numeral": "^1.5.3", - "react": "^0.13.1", - "react-router": "^0.13.2", - "react-select": "^0.6.12", - "react-tagsinput": "^1.0.0", - "recurly-js": "git://github.com/recurly/recurly-js#d9740eb3ee416fb999635daecfb524a492dbb058", - "remarkable": "^1.6.0", - "serialize-javascript": "^1.0.0", - "serve-favicon": "^2.2.0", - "superagent": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } -} diff --git a/app/.htaccess b/app/.htaccess deleted file mode 100644 index ca346584ca..0000000000 --- a/app/.htaccess +++ /dev/null @@ -1,663 +0,0 @@ -# Apache Server Configs v2.2.0 | MIT License -# https://github.com/h5bp/server-configs-apache - -# (!) Using `.htaccess` files slows down Apache, therefore, if you have access -# to the main server config file (usually called `httpd.conf`), you should add -# this logic there: http://httpd.apache.org/docs/current/howto/htaccess.html. - -# ############################################################################## -# # CROSS-ORIGIN RESOURCE SHARING (CORS) # -# ############################################################################## - -# ------------------------------------------------------------------------------ -# | Cross-domain AJAX requests | -# ------------------------------------------------------------------------------ - -# Allow cross-origin AJAX requests. -# http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity -# http://enable-cors.org/ - -# -# Header set Access-Control-Allow-Origin "*" -# - -# ------------------------------------------------------------------------------ -# | CORS-enabled images | -# ------------------------------------------------------------------------------ - -# Send the CORS header for images when browsers request it. -# https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image -# http://blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html -# http://hacks.mozilla.org/2011/11/using-cors-to-load-webgl-textures-from-cross-domain-images/ - - - - - SetEnvIf Origin ":" IS_CORS - Header set Access-Control-Allow-Origin "*" env=IS_CORS - - - - -# ------------------------------------------------------------------------------ -# | Web fonts access | -# ------------------------------------------------------------------------------ - -# Allow access to web fonts from all domains. - - - - Header set Access-Control-Allow-Origin "*" - - - - -# ############################################################################## -# # ERRORS # -# ############################################################################## - -# ------------------------------------------------------------------------------ -# | 404 error prevention for non-existing redirected folders | -# ------------------------------------------------------------------------------ - -# Prevent Apache from returning a 404 error as the result of a rewrite -# when the directory with the same name does not exist. -# http://httpd.apache.org/docs/current/content-negotiation.html#multiviews -# http://www.webmasterworld.com/apache/3808792.htm - -Options -MultiViews - -# ------------------------------------------------------------------------------ -# | Custom error messages / pages | -# ------------------------------------------------------------------------------ - -# Customize what Apache returns to the client in case of an error. -# http://httpd.apache.org/docs/current/mod/core.html#errordocument - -ErrorDocument 404 /404.html - - -# ############################################################################## -# # INTERNET EXPLORER # -# ############################################################################## - -# ------------------------------------------------------------------------------ -# | Better website experience | -# ------------------------------------------------------------------------------ - -# Force Internet Explorer to render pages in the highest available mode -# in the various cases when it may not. -# http://hsivonen.iki.fi/doctype/ie-mode.pdf - - - Header set X-UA-Compatible "IE=edge" - # `mod_headers` cannot match based on the content-type, however, this - # header should be send only for HTML pages and not for the other resources - - Header unset X-UA-Compatible - - - -# ------------------------------------------------------------------------------ -# | Cookie setting from iframes | -# ------------------------------------------------------------------------------ - -# Allow cookies to be set from iframes in Internet Explorer. -# http://msdn.microsoft.com/en-us/library/ms537343.aspx -# http://www.w3.org/TR/2000/CR-P3P-20001215/ - -# -# Header set P3P "policyref=\"/w3c/p3p.xml\", CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"" -# - - -# ############################################################################## -# # MIME TYPES AND ENCODING # -# ############################################################################## - -# ------------------------------------------------------------------------------ -# | Proper MIME types for all files | -# ------------------------------------------------------------------------------ - - - - # Audio - AddType audio/mp4 m4a f4a f4b - AddType audio/ogg oga ogg opus - - # Data interchange - AddType application/json json map - AddType application/ld+json jsonld - - # JavaScript - # Normalize to standard type. - # http://tools.ietf.org/html/rfc4329#section-7.2 - AddType application/javascript js - - # Video - AddType video/mp4 f4v f4p m4v mp4 - AddType video/ogg ogv - AddType video/webm webm - AddType video/x-flv flv - - # Web fonts - AddType application/font-woff woff - AddType application/vnd.ms-fontobject eot - - # Browsers usually ignore the font MIME types and simply sniff the bytes - # to figure out the font type. - # http://mimesniff.spec.whatwg.org/#matching-a-font-type-pattern - - # Chrome however, shows a warning if any other MIME types are used for - # the following fonts. - - AddType application/x-font-ttf ttc ttf - AddType font/opentype otf - - # Make SVGZ fonts work on the iPad. - # https://twitter.com/FontSquirrel/status/14855840545 - AddType image/svg+xml svgz - AddEncoding gzip svgz - - # Other - AddType application/octet-stream safariextz - AddType application/x-chrome-extension crx - AddType application/x-opera-extension oex - AddType application/x-web-app-manifest+json webapp - AddType application/x-xpinstall xpi - AddType application/xml atom rdf rss xml - AddType image/webp webp - AddType image/x-icon cur - AddType text/cache-manifest appcache manifest - AddType text/vtt vtt - AddType text/x-component htc - AddType text/x-vcard vcf - - - -# ------------------------------------------------------------------------------ -# | UTF-8 encoding | -# ------------------------------------------------------------------------------ - -# Use UTF-8 encoding for anything served as `text/html` or `text/plain`. -AddDefaultCharset utf-8 - -# Force UTF-8 for certain file formats. - - AddCharset utf-8 .atom .css .js .json .jsonld .rss .vtt .webapp .xml - - - -# ############################################################################## -# # URL REWRITES # -# ############################################################################## - -# ------------------------------------------------------------------------------ -# | Rewrite engine | -# ------------------------------------------------------------------------------ - -# Turn on the rewrite engine and enable the `FollowSymLinks` option (this is -# necessary in order for the following directives to work). - -# If your web host doesn't allow the `FollowSymlinks` option, you may need to -# comment it out and use `Options +SymLinksIfOwnerMatch`, but be aware of the -# performance impact. -# http://httpd.apache.org/docs/current/misc/perf-tuning.html#symlinks - -# Also, some cloud hosting services require `RewriteBase` to be set. -# http://www.rackspace.com/knowledge_center/frequently-asked-question/why-is-mod-rewrite-not-working-on-my-site - - - Options +FollowSymlinks - # Options +SymLinksIfOwnerMatch - RewriteEngine On - # RewriteBase / - - -# ------------------------------------------------------------------------------ -# | Suppressing / Forcing the `www.` at the beginning of URLs | -# ------------------------------------------------------------------------------ - -# The same content should never be available under two different URLs, -# especially not with and without `www.` at the beginning. This can cause -# SEO problems (duplicate content), and therefore, you should choose one -# of the alternatives and redirect the other one. - -# By default `Option 1` (no `www.`) is activated. -# http://no-www.org/faq.php?q=class_b - -# If you would prefer to use `Option 2`, just comment out all the lines -# from `Option 1` and uncomment the ones from `Option 2`. - -# IMPORTANT: NEVER USE BOTH RULES AT THE SAME TIME! - -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# Option 1: rewrite www.example.com → example.com - - - RewriteCond %{HTTPS} !=on - RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] - RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L] - - -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# Option 2: rewrite example.com → www.example.com - -# Be aware that the following might not be a good idea if you use "real" -# subdomains for certain parts of your website. - -# -# RewriteCond %{HTTPS} !=on -# RewriteCond %{HTTP_HOST} !^www\. [NC] -# RewriteCond %{SERVER_ADDR} !=127.0.0.1 -# RewriteCond %{SERVER_ADDR} !=::1 -# RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L] -# - - -# ############################################################################## -# # SECURITY # -# ############################################################################## - -# ------------------------------------------------------------------------------ -# | Clickjacking | -# ------------------------------------------------------------------------------ - -# Protect website against clickjacking. - -# The example below sends the `X-Frame-Options` response header with the value -# `DENY`, informing browsers not to display the web page content in any frame. - -# This might not be the best setting for everyone. You should read about the -# other two possible values for `X-Frame-Options`: `SAMEORIGIN` & `ALLOW-FROM`. -# http://tools.ietf.org/html/rfc7034#section-2.1 - -# Keep in mind that while you could send the `X-Frame-Options` header for all -# of your site’s pages, this has the potential downside that it forbids even -# non-malicious framing of your content (e.g.: when users visit your site using -# a Google Image Search results page). - -# Nonetheless, you should ensure that you send the `X-Frame-Options` header for -# all pages that allow a user to make a state changing operation (e.g: pages -# that contain one-click purchase links, checkout or bank-transfer confirmation -# pages, pages that make permanent configuration changes, etc.). - -# Sending the `X-Frame-Options` header can also protect your website against -# more than just clickjacking attacks: https://cure53.de/xfo-clickjacking.pdf. - -# http://tools.ietf.org/html/rfc7034 -# http://blogs.msdn.com/b/ieinternals/archive/2010/03/30/combating-clickjacking-with-x-frame-options.aspx -# https://www.owasp.org/index.php/Clickjacking - -# -# Header set X-Frame-Options "DENY" -# -# Header unset X-Frame-Options -# -# - -# ------------------------------------------------------------------------------ -# | Content Security Policy (CSP) | -# ------------------------------------------------------------------------------ - -# Mitigate the risk of cross-site scripting and other content-injection attacks. - -# This can be done by setting a `Content Security Policy` which whitelists -# trusted sources of content for your website. - -# The example header below allows ONLY scripts that are loaded from the current -# site's origin (no inline scripts, no CDN, etc). This almost certainly won't -# work as-is for your site! - -# For more details on how to craft a reasonable policy for your site, read: -# http://html5rocks.com/en/tutorials/security/content-security-policy (or the -# specification: http://w3.org/TR/CSP). Also, to make things easier, you can -# use an online CSP header generator such as: http://cspisawesome.com/. - -# -# Header set Content-Security-Policy "script-src 'self'; object-src 'self'" -# -# Header unset Content-Security-Policy -# -# - -# ------------------------------------------------------------------------------ -# | File access | -# ------------------------------------------------------------------------------ - -# Block access to directories without a default document. -# You should leave the following uncommented, as you shouldn't allow anyone to -# surf through every directory on your server (which may includes rather private -# places such as the CMS's directories). - - - Options -Indexes - - -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# Block access to hidden files and directories. -# This includes directories used by version control systems such as Git and SVN. - - - RewriteCond %{SCRIPT_FILENAME} -d [OR] - RewriteCond %{SCRIPT_FILENAME} -f - RewriteRule "(^|/)\." - [F] - - -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# Block access to files that can expose sensitive information. - -# By default, block access to backup and source files that may be left by some -# text editors and can pose a security risk when anyone has access to them. -# http://feross.org/cmsploit/ - -# IMPORTANT: Update the `` regular expression from below to include -# any files that might end up on your production server and can expose sensitive -# information about your website. These files may include: configuration files, -# files that contain metadata about the project (e.g.: project dependencies), -# build scripts, etc.. - - - - # Apache < 2.3 - - Order allow,deny - Deny from all - Satisfy All - - - # Apache ≥ 2.3 - - Require all denied - - - - -# ------------------------------------------------------------------------------ -# | Reducing MIME-type security risks | -# ------------------------------------------------------------------------------ - -# Prevent some browsers from MIME-sniffing the response. - -# This reduces exposure to drive-by download attacks and should be enable -# especially if the web server is serving user uploaded content, content -# that could potentially be treated by the browser as executable. - -# http://blogs.msdn.com/b/ie/archive/2008/07/02/ie8-security-part-v-comprehensive-protection.aspx -# http://msdn.microsoft.com/en-us/library/ie/gg622941.aspx -# http://mimesniff.spec.whatwg.org/ - -# -# Header set X-Content-Type-Options "nosniff" -# - -# ------------------------------------------------------------------------------ -# | Reflected Cross-Site Scripting (XSS) attacks | -# ------------------------------------------------------------------------------ - -# (1) Try to re-enable the Cross-Site Scripting (XSS) filter built into the -# most recent web browsers. -# -# The filter is usually enabled by default, but in some cases it may be -# disabled by the user. However, in Internet Explorer for example, it can -# be re-enabled just by sending the `X-XSS-Protection` header with the -# value of `1`. -# -# (2) Prevent web browsers from rendering the web page if a potential reflected -# (a.k.a non-persistent) XSS attack is detected by the filter. -# -# By default, if the filter is enabled and browsers detect a reflected -# XSS attack, they will attempt to block the attack by making the smallest -# possible modifications to the returned web page. -# -# Unfortunately, in some browsers (e.g.: Internet Explorer), this default -# behavior may allow the XSS filter to be exploited, thereby, it's better -# to tell browsers to prevent the rendering of the page altogether, instead -# of attempting to modify it. -# -# http://hackademix.net/2009/11/21/ies-xss-filter-creates-xss-vulnerabilities -# -# IMPORTANT: Do not rely on the XSS filter to prevent XSS attacks! Ensure that -# you are taking all possible measures to prevent XSS attacks, the most obvious -# being: validating and sanitizing your site's inputs. -# -# http://blogs.msdn.com/b/ie/archive/2008/07/02/ie8-security-part-iv-the-xss-filter.aspx -# http://blogs.msdn.com/b/ieinternals/archive/2011/01/31/controlling-the-internet-explorer-xss-filter-with-the-x-xss-protection-http-header.aspx -# https://www.owasp.org/index.php/Cross-site_Scripting_%28XSS%29 - -# -# # (1) (2) -# Header set X-XSS-Protection "1; mode=block" -# -# Header unset X-XSS-Protection -# -# - -# ------------------------------------------------------------------------------ -# | Secure Sockets Layer (SSL) | -# ------------------------------------------------------------------------------ - -# Rewrite secure requests properly in order to prevent SSL certificate warnings. -# E.g.: prevent `https://www.example.com` when your certificate only allows -# `https://secure.example.com`. - -# -# RewriteCond %{SERVER_PORT} !^443 -# RewriteRule ^ https://example-domain-please-change-me.com%{REQUEST_URI} [R=301,L] -# - -# ------------------------------------------------------------------------------ -# | HTTP Strict Transport Security (HSTS) | -# ------------------------------------------------------------------------------ - -# Force client-side SSL redirection. - -# If a user types `example.com` in his browser, the above rule will redirect -# him to the secure version of the site. That still leaves a window of -# opportunity (the initial HTTP connection) for an attacker to downgrade or -# redirect the request. - -# The following header ensures that browser will ONLY connect to your server -# via HTTPS, regardless of what the users type in the address bar. - -# http://tools.ietf.org/html/draft-ietf-websec-strict-transport-sec-14#section-6.1 -# http://www.html5rocks.com/en/tutorials/security/transport-layer-security/ - -# IMPORTANT: Remove the `includeSubDomains` optional directive if the subdomains -# are not using HTTPS. - -# -# Header set Strict-Transport-Security "max-age=16070400; includeSubDomains" -# - -# ------------------------------------------------------------------------------ -# | Server software information | -# ------------------------------------------------------------------------------ - -# Avoid displaying the exact Apache version number, the description of the -# generic OS-type and the information about Apache's compiled-in modules. - -# ADD THIS DIRECTIVE IN THE `httpd.conf` AS IT WILL NOT WORK IN THE `.htaccess`! - -# ServerTokens Prod - - -# ############################################################################## -# # WEB PERFORMANCE # -# ############################################################################## - -# ------------------------------------------------------------------------------ -# | Compression | -# ------------------------------------------------------------------------------ - - - - # Force compression for mangled headers. - # http://developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping - - - SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding - RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding - - - - # Compress all output labeled with one of the following MIME-types - # (for Apache versions below 2.3.7, you don't need to enable `mod_filter` - # and can remove the `` and `` lines - # as `AddOutputFilterByType` is still in the core directives). - - AddOutputFilterByType DEFLATE application/atom+xml \ - application/javascript \ - application/json \ - application/ld+json \ - application/rss+xml \ - application/vnd.ms-fontobject \ - application/x-font-ttf \ - application/x-web-app-manifest+json \ - application/xhtml+xml \ - application/xml \ - font/opentype \ - image/svg+xml \ - image/x-icon \ - text/css \ - text/html \ - text/plain \ - text/x-component \ - text/xml - - - - -# ------------------------------------------------------------------------------ -# | Content transformations | -# ------------------------------------------------------------------------------ - -# Prevent mobile network providers from modifying the website's content. -# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.5. - -# -# Header set Cache-Control "no-transform" -# - -# ------------------------------------------------------------------------------ -# | ETags | -# ------------------------------------------------------------------------------ - -# Remove `ETags` as resources are sent with far-future expires headers. -# http://developer.yahoo.com/performance/rules.html#etags. - -# `FileETag None` doesn't work in all cases. - - Header unset ETag - - -FileETag None - -# ------------------------------------------------------------------------------ -# | Expires headers | -# ------------------------------------------------------------------------------ - -# The following expires headers are set pretty far in the future. If you -# don't control versioning with filename-based cache busting, consider -# lowering the cache time for resources such as style sheets and JavaScript -# files to something like one week. - - - - ExpiresActive on - ExpiresDefault "access plus 1 month" - - # CSS - ExpiresByType text/css "access plus 1 year" - - # Data interchange - ExpiresByType application/json "access plus 0 seconds" - ExpiresByType application/ld+json "access plus 0 seconds" - ExpiresByType application/xml "access plus 0 seconds" - ExpiresByType text/xml "access plus 0 seconds" - - # Favicon (cannot be renamed!) and cursor images - ExpiresByType image/x-icon "access plus 1 week" - - # HTML components (HTCs) - ExpiresByType text/x-component "access plus 1 month" - - # HTML - ExpiresByType text/html "access plus 0 seconds" - - # JavaScript - ExpiresByType application/javascript "access plus 1 year" - - # Manifest files - ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds" - ExpiresByType text/cache-manifest "access plus 0 seconds" - - # Media - ExpiresByType audio/ogg "access plus 1 month" - ExpiresByType image/gif "access plus 1 month" - ExpiresByType image/jpeg "access plus 1 month" - ExpiresByType image/png "access plus 1 month" - ExpiresByType video/mp4 "access plus 1 month" - ExpiresByType video/ogg "access plus 1 month" - ExpiresByType video/webm "access plus 1 month" - - # Web feeds - ExpiresByType application/atom+xml "access plus 1 hour" - ExpiresByType application/rss+xml "access plus 1 hour" - - # Web fonts - ExpiresByType application/font-woff "access plus 1 month" - ExpiresByType application/vnd.ms-fontobject "access plus 1 month" - ExpiresByType application/x-font-ttf "access plus 1 month" - ExpiresByType font/opentype "access plus 1 month" - ExpiresByType image/svg+xml "access plus 1 month" - - - -# ------------------------------------------------------------------------------ -# | Filename-based cache busting | -# ------------------------------------------------------------------------------ - -# If you're not using a build process to manage your filename version revving, -# you might want to consider enabling the following directives to route all -# requests such as `/css/style.12345.css` to `/css/style.css`. - -# To understand why this is important and a better idea than `*.css?v231`, read: -# http://stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring - -# -# RewriteCond %{REQUEST_FILENAME} !-f -# RewriteRule ^(.+)\.(\d+)\.(js|css|png|jpe?g|gif)$ $1.$3 [L] -# - -# ------------------------------------------------------------------------------ -# | File concatenation | -# ------------------------------------------------------------------------------ - -# Allow concatenation from within specific style sheets and JavaScript files. - -# e.g.: -# -# If you have the following content in a file -# -# -# -# -# Apache will replace it with the content from the specified files. - -# -# -# Options +Includes -# AddOutputFilterByType INCLUDES application/javascript application/json -# SetOutputFilter INCLUDES -# -# -# Options +Includes -# AddOutputFilterByType INCLUDES text/css -# SetOutputFilter INCLUDES -# -# diff --git a/app/favicon.ico b/app/favicon.ico deleted file mode 100644 index ee01a5ee8a..0000000000 Binary files a/app/favicon.ico and /dev/null differ diff --git a/app/fonts/FontAwesome.otf b/app/fonts/FontAwesome.otf deleted file mode 100644 index 681bdd4d4c..0000000000 Binary files a/app/fonts/FontAwesome.otf and /dev/null differ diff --git a/app/fonts/fontawesome-webfont.eot b/app/fonts/fontawesome-webfont.eot deleted file mode 100644 index a30335d748..0000000000 Binary files a/app/fonts/fontawesome-webfont.eot and /dev/null differ diff --git a/app/fonts/fontawesome-webfont.svg b/app/fonts/fontawesome-webfont.svg deleted file mode 100644 index 6fd19abcb9..0000000000 --- a/app/fonts/fontawesome-webfont.svg +++ /dev/null @@ -1,640 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/fonts/fontawesome-webfont.ttf b/app/fonts/fontawesome-webfont.ttf deleted file mode 100644 index d7994e1308..0000000000 Binary files a/app/fonts/fontawesome-webfont.ttf and /dev/null differ diff --git a/app/fonts/fontawesome-webfont.woff b/app/fonts/fontawesome-webfont.woff deleted file mode 100644 index 6fd4ede0f3..0000000000 Binary files a/app/fonts/fontawesome-webfont.woff and /dev/null differ diff --git a/app/fonts/fontawesome-webfont.woff2 b/app/fonts/fontawesome-webfont.woff2 deleted file mode 100644 index 5560193ccc..0000000000 Binary files a/app/fonts/fontawesome-webfont.woff2 and /dev/null differ diff --git a/app/img/docker-logos/docker-logo.svg b/app/img/docker-logos/docker-logo.svg deleted file mode 100644 index 91c8e453fd..0000000000 --- a/app/img/docker-logos/docker-logo.svg +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/img/docker-logos/docker_logo-01.svg b/app/img/docker-logos/docker_logo-01.svg deleted file mode 100644 index c5f6b41245..0000000000 --- a/app/img/docker-logos/docker_logo-01.svg +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/img/docker-logos/docker_logo-02.svg b/app/img/docker-logos/docker_logo-02.svg deleted file mode 100644 index 381aa6456c..0000000000 --- a/app/img/docker-logos/docker_logo-02.svg +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/img/docker-logos/docker_logo-03.svg b/app/img/docker-logos/docker_logo-03.svg deleted file mode 100644 index 0e3c0e22ed..0000000000 --- a/app/img/docker-logos/docker_logo-03.svg +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/img/docker-logos/docker_logo-04.svg b/app/img/docker-logos/docker_logo-04.svg deleted file mode 100644 index e06ac3f06b..0000000000 --- a/app/img/docker-logos/docker_logo-04.svg +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/img/docker-logos/docker_logo-05.svg b/app/img/docker-logos/docker_logo-05.svg deleted file mode 100644 index 4fbbf3671d..0000000000 --- a/app/img/docker-logos/docker_logo-05.svg +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/img/docker-logos/docker_logo-06.svg b/app/img/docker-logos/docker_logo-06.svg deleted file mode 100644 index cc0bccbdff..0000000000 --- a/app/img/docker-logos/docker_logo-06.svg +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/img/docker-logos/docker_logo-07.svg b/app/img/docker-logos/docker_logo-07.svg deleted file mode 100644 index 6cb705a9bd..0000000000 --- a/app/img/docker-logos/docker_logo-07.svg +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/img/docker-logos/docker_logo-08.svg b/app/img/docker-logos/docker_logo-08.svg deleted file mode 100644 index 28734a80b3..0000000000 --- a/app/img/docker-logos/docker_logo-08.svg +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/img/services/bitbucket-logo.png b/app/img/services/bitbucket-logo.png deleted file mode 100644 index f3c9a9aa95..0000000000 Binary files a/app/img/services/bitbucket-logo.png and /dev/null differ diff --git a/app/img/services/github-logo.png b/app/img/services/github-logo.png deleted file mode 100644 index 582c451dac..0000000000 Binary files a/app/img/services/github-logo.png and /dev/null differ diff --git a/app/img/services/gitlab-logo.png b/app/img/services/gitlab-logo.png deleted file mode 100644 index 1b5d498261..0000000000 Binary files a/app/img/services/gitlab-logo.png and /dev/null differ diff --git a/app/robots.txt b/app/robots.txt deleted file mode 100644 index ee2cc216a6..0000000000 --- a/app/robots.txt +++ /dev/null @@ -1,3 +0,0 @@ -# robotstxt.org/ - -User-agent: * diff --git a/app/scripts/actions/addAutoBuildPushTriggerItem.js b/app/scripts/actions/addAutoBuildPushTriggerItem.js deleted file mode 100644 index a21b202150..0000000000 --- a/app/scripts/actions/addAutoBuildPushTriggerItem.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -export default function(actionContext) { - actionContext.dispatch('ADD_AUTOBUILD_PUSH_TRIGGER_ITEM'); -} diff --git a/app/scripts/actions/addCollaborator.js b/app/scripts/actions/addCollaborator.js deleted file mode 100644 index 37525ee890..0000000000 --- a/app/scripts/actions/addCollaborator.js +++ /dev/null @@ -1,29 +0,0 @@ -'use strict'; -import { Repositories } from 'hub-js-sdk'; -const { addCollaborator, getCollaboratorsForRepo } = Repositories; -import has from 'lodash/object/has'; -const debug = require('debug')('hub:actions:addCollaborator'); - -export default function addCollaboratorAction(actionContext, {JWT, namespace, name, user}, done) { - actionContext.dispatch('ADD_COLLAB_START'); - addCollaborator(JWT, { namespace, name, user }, (err, res) => { - if(err) { - if(has(err.response.body, 'detail')) { - debug('failed'); - actionContext.dispatch('ADD_COLLAB_ERROR', err.response.body.detail); - } - } else { - debug('succeeded'); - actionContext.dispatch('ADD_COLLAB_SUCCESS'); - getCollaboratorsForRepo(JWT, `${namespace}/${name}`, (getErr, getRes) => { - if(getErr) { - // 'Org repositories do not have collaborators.' - actionContext.dispatch('COLLAB_RECEIVE_COLLABORATORS', {}); - } else { - actionContext.dispatch('COLLAB_RECEIVE_COLLABORATORS', getRes.body); - } - }); - } - done(); - }); -} diff --git a/app/scripts/actions/addPipeline.js b/app/scripts/actions/addPipeline.js deleted file mode 100644 index b25996c516..0000000000 --- a/app/scripts/actions/addPipeline.js +++ /dev/null @@ -1,58 +0,0 @@ -'use strict'; - -import includes from 'lodash/collection/includes'; - -import createPipeline from '@dux/hub-sdk/webhooks/createPipeline'; -import MissingArgError from '@dux/hub-sdk/utils/MissingArgError'; -import ValidationError from '@dux/hub-sdk/utils/ValidationError'; - -function handleKnownErrors(err, dispatch) { - if(err instanceof MissingArgError) { - if(includes(err.missingArgs, 'namespace') || includes(err.missingArgs, 'name')) { - /** - * TODO: send something to bugsnag; The user doesn't control these values - * This can happen if an engineer forgets to pass in a required value that - * the user can't control - */ - dispatch('ADD_WEBHOOK_ERROR'); - } else { - dispatch('ADD_WEBHOOK_MISSING_ARGS', err.missingArgs); - } - } else if (err instanceof ValidationError) { - dispatch('ADD_WEBHOOK_VALIDATION_ERRORS', err.validationErrors); - } else { - // unknown error - dispatch('ADD_WEBHOOK_ERROR', err); - } -} - -export default function addPipeline({ dispatch, history }, - { - jwt, - namespace, - name, - pipelineName, - expectFinalCallback, - webhooks - }, - done) { - dispatch('ADD_WEBHOOK_START'); - createPipeline(jwt, - { - namespace, - name, - pipelineName, - expectFinalCallback, - webhooks - }, - (err, res) => { - if(err || !res.ok) { - handleKnownErrors(err, dispatch); - done(); - } else { - dispatch('ADD_WEBHOOK_SUCCESS'); - history.push(`/r/${namespace}/${name}/~/settings/webhooks/`); - done(); - } - }); -} diff --git a/app/scripts/actions/addRepoComment.js b/app/scripts/actions/addRepoComment.js deleted file mode 100644 index 3c0a30cb6a..0000000000 --- a/app/scripts/actions/addRepoComment.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; - -var debug = require('debug')('hub:actions:addRepoComment'); - -import { Repositories } from 'hub-js-sdk'; - -var addRepoComment = function(actionContext, {jwt, repoShortName, comment}) { - Repositories.addCommentToRepo(jwt, repoShortName, comment, function(addErr, addRes) { - if (addErr) { - debug(addErr); - } else if (addRes.body && addRes.ok) { - Repositories.getCommentsForRepo(jwt, repoShortName, function(getErr, getRes) { - if (getErr) { - debug(getErr); - } else { - actionContext.dispatch('RECEIVE_REPO_COMMENTS', getRes.body); - } - }, 1); - } - }); - -}; - -module.exports = addRepoComment; diff --git a/app/scripts/actions/addTeamCollaborator.js b/app/scripts/actions/addTeamCollaborator.js deleted file mode 100644 index e9e178b067..0000000000 --- a/app/scripts/actions/addTeamCollaborator.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; -import { - Repositories as R - } from 'hub-js-sdk'; -const debug = require('debug')('hub:actions:addCollaborator'); - -export default function addTeamCollaborator(actionContext, {JWT, namespace, name, id, permission}, done) { - actionContext.dispatch('ADD_COLLAB_START'); - R.addTeamCollaborator(JWT, { namespace, name, group_id: id, permission }, (err, res) => { - if(err) { - debug('failed'); - } else { - debug('succeeded'); - R.getTeamCollaboratorsForRepo(JWT, `${namespace}/${name}`, (getErr, getRes) => { - if (getErr) { - // 'User repository does not have any teams yet' - actionContext.dispatch('COLLAB_RECEIVE_TEAMS', {}); - } else { - actionContext.dispatch('COLLAB_RECEIVE_TEAMS', getRes.body); - } - }); - } - actionContext.dispatch('ADD_COLLAB_FINISH'); - done(); - }); -} diff --git a/app/scripts/actions/addTriggerLink.js b/app/scripts/actions/addTriggerLink.js deleted file mode 100644 index 1df118c658..0000000000 --- a/app/scripts/actions/addTriggerLink.js +++ /dev/null @@ -1,23 +0,0 @@ -'use strict'; -import _ from 'lodash'; -import { Autobuilds as AutoBuild } from 'hub-js-sdk'; -var debug = require('debug')('hub:actions:addTriggerLink'); - -export default function(actionContext, { JWT, namespace, name, to_repo }) { - // to_repo needs to be a repo id - AutoBuild.addAutomatedBuildLink(JWT, namespace, name, to_repo, function(err, res) { - if (err) { - debug(err); - actionContext.dispatch('LINK_AUTOBUILD_ERROR'); - } else { - actionContext.dispatch('LINK_AUTOBUILD_SUCCESS'); - AutoBuild.getAutomatedBuildLinks(JWT, namespace, name, function(getErr, getRes){ - if (getErr) { - debug(err); - } else { - actionContext.dispatch('RECEIVE_AUTOBUILD_LINKS', getRes.body.results); - } - }); - } - }); -} diff --git a/app/scripts/actions/addUserEmail.js b/app/scripts/actions/addUserEmail.js deleted file mode 100644 index 3f67808bde..0000000000 --- a/app/scripts/actions/addUserEmail.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict'; - -import { sortByOrder } from 'lodash'; -import { - Emails - } from 'hub-js-sdk'; -var debug = require('debug')('hub:actions:addEmail'); - -module.exports = function(actionContext, - { - JWT, newEmail, user - }, - done) { - Emails.addEmailsForUser(JWT, user.username, newEmail, function(err, res) { - if (err) { - debug('error', res.body); - actionContext.dispatch('ADD_EMAIL_INVALID', res.body.email); - } else if (res.ok) { - actionContext.dispatch('ADD_EMAIL_SUCCESS', res.body.email); - Emails.getEmailsForUser(JWT, user.username, function(emailErr, emailRes){ - if (emailErr) { - return done(); - } - var emails = emailRes.body.results; - var sortedEmails = sortByOrder(emails, - ['primary', 'verified'], - [false, false]); - actionContext.dispatch('RECEIVE_EMAILS', { - emails: sortedEmails - }); - }); - } - }); -}; diff --git a/app/scripts/actions/addUserEmailChange.js b/app/scripts/actions/addUserEmailChange.js deleted file mode 100644 index 3be02615c6..0000000000 --- a/app/scripts/actions/addUserEmailChange.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -export default function(actionContext, { email }) { - actionContext.dispatch('UPDATE_ADD_EMAIL', email); -} diff --git a/app/scripts/actions/addWebhookToPipeline.jsx b/app/scripts/actions/addWebhookToPipeline.jsx deleted file mode 100644 index a2605beda8..0000000000 --- a/app/scripts/actions/addWebhookToPipeline.jsx +++ /dev/null @@ -1,8 +0,0 @@ -'use strict'; - -export default function addWebhookToPipeline({ dispatch }, - params, - done) { - dispatch('ADD_WEBHOOK_NEW_HOOK'); - done(); -} diff --git a/app/scripts/actions/associateGithubAccount.js b/app/scripts/actions/associateGithubAccount.js deleted file mode 100644 index caf33396a8..0000000000 --- a/app/scripts/actions/associateGithubAccount.js +++ /dev/null @@ -1,23 +0,0 @@ -'use strict'; - -var debug = require('debug')('hub:actions:associateGithubAccount'); -import has from 'lodash/object/has'; -import { Builds } from 'hub-js-sdk'; - -export default function(actionContext, {jwt, code}) { - //TODO: immediately call the linked accounts status and update the authorized services page - Builds.associateGithubAccount(jwt, code, function(err, res) { - if (err) { - debug('error', err); - const { detail } = err.response.body; - if(detail) { - actionContext.dispatch('GITHUB_ASSOCIATE_ERROR', detail); - } - } else { - if (res.body) { - actionContext.dispatch('GITHUB_ASSOCIATE_SUCCESS', res.body); - } - } - }); - actionContext.dispatch(); -} diff --git a/app/scripts/actions/attemptChangeLongDescription.js b/app/scripts/actions/attemptChangeLongDescription.js deleted file mode 100644 index f976b9ad49..0000000000 --- a/app/scripts/actions/attemptChangeLongDescription.js +++ /dev/null @@ -1,56 +0,0 @@ -/* @flow */ -'use strict'; - -import { Repositories as Repos } from 'hub-js-sdk'; -import async from 'async'; -import { PENDING_DELETE } from 'common/enums/RepoStatus'; -var debug = require('debug')('hub:actions:attemptChangeLongDescription'); - -export default function(actionContext, - {jwt, repoShortName, longDescription}, - done) { - actionContext.dispatch('LONG_DESCRIPTION_ATTEMPT_START'); - - var _updateLongDescription = function(cb) { - Repos.patchRepo(jwt, repoShortName, { - full_description: longDescription - }, function(err, res) { - if (err) { - if(res && res.badRequest) { - debug('error', err); - actionContext.dispatch('LONG_BAD_REQUEST', res.body); - cb(err); - } else { - actionContext.dispatch('DETAILS_ERROR'); - cb(err); - } - } else { - actionContext.dispatch('LONG_DESCRIPTION_SUCCESS'); - cb(null, res.body); - } - }); - }; - - var _getRepoDetails = function(cb) { - Repos.getRepo(jwt, repoShortName, function(err, res) { - const { status, detail } = res.body; - - if (err || status === PENDING_DELETE) { - actionContext.dispatch('REPO_NOT_FOUND', err); - cb(null, detail); - } else { - actionContext.dispatch('RECEIVE_REPOSITORY', res.body); - cb(null, res.body); - } - }); - }; - - async.series([ - _updateLongDescription, - _getRepoDetails - ], function (err, results) { - if(err) { - debug('error', err); - } - }); -} diff --git a/app/scripts/actions/attemptChangeShortDescription.js b/app/scripts/actions/attemptChangeShortDescription.js deleted file mode 100644 index 725b7f5972..0000000000 --- a/app/scripts/actions/attemptChangeShortDescription.js +++ /dev/null @@ -1,58 +0,0 @@ -/* @flow */ -'use strict'; - -import async from 'async'; -import { Repositories as Repos } from 'hub-js-sdk'; -import { PENDING_DELETE } from 'common/enums/RepoStatus'; -var debug = require('debug')('hub:actions:attemptChangeShortDescription'); - -export default function(actionContext, - {jwt, repoShortName, shortDescription}, - done) { - actionContext.dispatch('SHORT_DESCRIPTION_ATTEMPT_START'); - - var name = repoShortName.split('/')[1]; - var namespace = repoShortName.split('/')[0]; - var _updateShortDescription = function(cb) { - Repos.patchRepo(jwt, repoShortName, {description: shortDescription}, - function(err, res) { - if (err) { - if(res && res.badRequest) { - debug('error', err); - actionContext.dispatch('SHORT_BAD_REQUEST', res.body); - cb(err); - } else { - actionContext.dispatch('DETAILS_ERROR'); - cb(err); - } - } else { - actionContext.dispatch('SHORT_DESCRIPTION_SUCCESS'); - cb(null, res.body); - } - } - ); - }; - - var _getRepoDetails = function(cb) { - Repos.getRepo(jwt, repoShortName, function(err, res) { - const { status, detail } = res.body; - - if (err || status === PENDING_DELETE) { - actionContext.dispatch('REPO_NOT_FOUND', err); - cb(null, detail); - } else { - actionContext.dispatch('RECEIVE_REPOSITORY', res.body); - cb(null, res.body); - } - }); - }; - - async.series([ - _updateShortDescription, - _getRepoDetails - ], function (err, results) { - if(err) { - debug('error', err); - } - }); -} diff --git a/app/scripts/actions/attemptLogin.js b/app/scripts/actions/attemptLogin.js deleted file mode 100644 index f0c0fe707f..0000000000 --- a/app/scripts/actions/attemptLogin.js +++ /dev/null @@ -1,147 +0,0 @@ -'use strict'; - -import { parallel, waterfall } from 'async'; -import { Auth, - Repositories as Repos - } from 'hub-js-sdk'; -var debug = require('debug')('hub:actions:attemptLogin'); -import { getActivityFeed } from 'hub-js-sdk/src/Hub/SDK/Notifications'; -import { getUser } from 'hub-js-sdk/src/Hub/SDK/JWT'; -import { - getOrgsForUser, - getUserSettings -} from 'hub-js-sdk/src/Hub/SDK/Users'; -import { getToken } from 'hub-js-sdk/src/Hub/SDK/Auth'; -import request from 'superagent'; - -function handleGetRepos({jwt, username, dispatch}) { - return function(callback) { - Repos.getReposForUser(jwt, username, function(err, res) { - if (err) { - callback(null, null); - } else { - dispatch('RECEIVE_REPOS', res.body); - } - }, 1); //get page 1 - }; -} - -function handleGetPrivateRepoStats({jwt, username, dispatch}) { - return function(callback) { - getUserSettings(jwt, username, function(err, res) { - if (res.ok) { - dispatch('RECEIVE_PRIVATE_REPOSTATS', res.body); - } - callback(null, null); - }); - }; -} - -//Get orgs for user -function _getOrgsForCurrentUser({jwt, username, dispatch}) { - return function(user, cb) { - getOrgsForUser(jwt, function(err, res) { - if (err) { - debug('error', err); - cb(null); - } else { - dispatch('RECEIVE_DASHBOARD_NAMESPACES', { - orgs: res.body, - user: user.username - }); - cb(null, user); - } - }); - }; -} - -function handleGetUserInfo({jwt, username, dispatch}, callback) { - waterfall([ - function(cb){ - getUser(jwt, function(err, res) { - if (err) { - cb(err, {}); - } else { - dispatch('RECEIVE_USER', res.body); - cb(null, res.body); - } - }); - }, - _getOrgsForCurrentUser({jwt, username, dispatch}) - ], function(err, user) { - callback(err, { user }); - }); -} - -function fetchDataForDashboard({ - jwt, username, dispatch, done -}) { - dispatch('RECEIVE_JWT', jwt); - dispatch('DASHBOARD_REPOS_STORE_ATTEMPTING_GET_REPOS'); - parallel([ - handleGetRepos({jwt, username, dispatch}), - handleGetPrivateRepoStats({jwt, username, dispatch}) - ], function(err, results) { - if (err) { - debug('error', err); - } - return done(); - }); -} - -module.exports = function({ dispatch, history }, - { username, password }, - done) { - dispatch('LOGIN_ATTEMPT_START'); - getToken(username, - password, - function(err, res) { - if (err) { - debug('error', err); - if (res.unauthorized) { - if(res.body && res.body.detail) { - /** - * This can happen if the user has not verified their email - */ - dispatch('LOGIN_UNAUTHORIZED_DETAIL', res.body); - } else { - dispatch('LOGIN_UNAUTHORIZED'); - } - } else if (res.badRequest){ - try { - dispatch('LOGIN_BAD_REQUEST', JSON.parse(res.text)); - } catch (error) { - dispatch('LOGIN_ERROR'); - } - } else { - // unhandled login error - dispatch('LOGIN_ERROR'); - } - } else { - debug('got token'); - if (res.body.token) { - request.post('/attempt-login/') - .send({jwt: res.body.token}) - .end((cookieErr, cookieRes) => { - handleGetUserInfo({ - jwt: res.body.token, - username, - dispatch - }, function(userErr, userRes) { - dispatch('LOGIN_CLEAR'); - dispatch('CURRENT_USER_CONTEXT', { - username: userRes.user.username - }); - history.pushState(null, '/'); - fetchDataForDashboard({ - jwt: res.body.token, - username: userRes.user.username, - dispatch, - done - }); - }); - }); - } - } - }); -}; diff --git a/app/scripts/actions/attemptSignup.js b/app/scripts/actions/attemptSignup.js deleted file mode 100644 index 197e35bc5d..0000000000 --- a/app/scripts/actions/attemptSignup.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict'; - -import { Auth } from 'hub-js-sdk'; -import type FluxibleActionContext from '../../../flow-libs/fluxible'; -var debug = require('debug')('hub:actions:attemptSignup'); - -type SignupPayload = { - username: String; - password: String; - email: String; -}; - -module.exports = function(actionContext: FluxibleActionContext, - payload: SignupPayload, - done: Function) { - actionContext.dispatch('SIGNUP_ATTEMPT_START'); - Auth.signup(payload, function(err, res) { - if (err) { - debug('error', err); - if (res.badRequest){ - actionContext.dispatch('SIGNUP_BAD_REQUEST', res.body); - } else { - done(); - } - actionContext.dispatch('SIGNUP_CLEAR_PASSWORD'); - } else { - actionContext.dispatch('SIGNUP_SUCCESS'); - } - }); -}; diff --git a/app/scripts/actions/changePassword.js b/app/scripts/actions/changePassword.js deleted file mode 100644 index d38d26dede..0000000000 --- a/app/scripts/actions/changePassword.js +++ /dev/null @@ -1,48 +0,0 @@ -'use strict'; - -import { getToken, logout } from 'hub-js-sdk/src/Hub/SDK/Auth'; -import { changePassword } from 'hub-js-sdk/src/Hub/SDK/Users'; -import async from 'async'; -import request from 'superagent'; -var debug = require('debug')('hub:actions:changePassword'); - -var changePassAction = function({ dispatch, history }, - { - JWT, username, oldpassword, newpassword - }) { - changePassword( - JWT, - {username, oldpassword, newpassword}, - (err, res) => { - - if (err) { - debug('error', err); - dispatch('RESET_PASSWORD_ERROR', res.body); - } else if (res.ok) { - dispatch('CHANGE_PASS_SUCCESS'); - async.parallel([ - function(callback) { - logout(JWT, function(outErr, outRes) { - if (outErr) { - debug('outErr', outErr); - dispatch('LOGOUT_ERROR', outErr); - } else if (outRes.ok) { - dispatch('CHANGE_PASS_CLEAR', {}); - history.pushState(null, '/account/password-reset-confirm/success/'); - dispatch('LOGOUT'); - } - }); - }, - function(callback) { - request.post('/attempt-logout/') - .end(callback); - }], - function(asyncErr, asyncRes) { - - }); - } - } - ); -}; - -module.exports = changePassAction; diff --git a/app/scripts/actions/clearChangePasswordStore.js b/app/scripts/actions/clearChangePasswordStore.js deleted file mode 100644 index 2ec0e9b123..0000000000 --- a/app/scripts/actions/clearChangePasswordStore.js +++ /dev/null @@ -1,8 +0,0 @@ -/* @flow */ -'use strict'; - -import type FluxibleActionContext from '../../../flow-libs/fluxible'; - -module.exports = function(actionContext: FluxibleActionContext) { - actionContext.dispatch('CHANGE_PASS_CLEAR', {}); -}; diff --git a/app/scripts/actions/clearCloudCoupon.js b/app/scripts/actions/clearCloudCoupon.js deleted file mode 100644 index 88147ed0f0..0000000000 --- a/app/scripts/actions/clearCloudCoupon.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -export default (actionContext) => { - actionContext.dispatch('CLEAR_CLOUD_COUPON'); -}; diff --git a/app/scripts/actions/clearLoginForm.js b/app/scripts/actions/clearLoginForm.js deleted file mode 100644 index c677a394a0..0000000000 --- a/app/scripts/actions/clearLoginForm.js +++ /dev/null @@ -1,8 +0,0 @@ -/* @flow */ -'use strict'; - -import type FluxibleActionContext from '../../../flow-libs/fluxible'; - -module.exports = function(actionContext: FluxibleActionContext) { - actionContext.dispatch('LOGIN_CLEAR', {}); -}; diff --git a/app/scripts/actions/clearMemberError.js b/app/scripts/actions/clearMemberError.js deleted file mode 100644 index 6fab18e28e..0000000000 --- a/app/scripts/actions/clearMemberError.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -export default function(actionContext) { - actionContext.dispatch('CLEAR_MEMBER_ERROR'); -} diff --git a/app/scripts/actions/cloudNamespaceChange.js b/app/scripts/actions/cloudNamespaceChange.js deleted file mode 100644 index 2947f1bb80..0000000000 --- a/app/scripts/actions/cloudNamespaceChange.js +++ /dev/null @@ -1,78 +0,0 @@ -'use strict'; - -const debug = require('debug')('hub:actions:cloudNamespaceChange'); -import async from 'async'; -import _ from 'lodash'; - -import { - Billing, - Users - } from 'hub-js-sdk'; - -//GETs current HUB subscription -function _getBillingSubscriptions({JWT, namespace}) { - return (callback) => { - Billing.getBillingSubscriptions(JWT, namespace, (err, res) => { - if(err) { - callback(null, {}); - } else { - let subscriptions = res.body; - - // the assumption is that there is at most one subscription right now - let subscription = _.head(subscriptions); - callback(null, subscription); - } - }); - }; -} - -function _getBillingAccount({JWT, namespace}) { - return (callback) => { - Billing.getBillingAccount(JWT, namespace, (err, res) => { - if(err) { - debug('getBillingAccount', 'no billing account connected'); - callback(null, {}); - } else { - callback(null, res.body); - } - }); - }; -} - -function _getBillingInfo({JWT, namespace}) { - return (callback) => { - Billing.getBillingInfo(JWT, namespace, (err, res) => { - if(err) { - debug('getBillingInfo', 'no billing account connected'); - callback(null, {}); - } else { - callback(null, res.body); - } - }); - }; -} - -export default function billingPlans(actionContext, {JWT, namespace}, done){ - actionContext.dispatch('RESET_CLOUD_BILLING_PLANS'); - async.parallel({ - userPlan: _getBillingSubscriptions({JWT, namespace}), - accountInfo: _getBillingAccount({JWT, namespace}), - billingInfo: _getBillingInfo({JWT, namespace}) - }, function(err, results){ - let { userPlan, accountInfo, billingInfo } = results; - actionContext.dispatch('RECEIVE_CLOUD_BILLING_INFO', { - billingInfo: billingInfo, - accountInfo: accountInfo, - currentPlan: userPlan - }); - let values = _.merge({}, billingInfo, { - account_first: accountInfo.first_name, - account_last: accountInfo.last_name, - company_name: accountInfo.company_name, - email: accountInfo.email - }); - // TODO: Need to differentiate btw billingInfo/accountInfo first/last names - actionContext.dispatch('ENTERPRISE_PAID_POPULATE_FORM', values); - return done(); - }); -} diff --git a/app/scripts/actions/common/onChangeUtil.js b/app/scripts/actions/common/onChangeUtil.js deleted file mode 100644 index 5672dd0bac..0000000000 --- a/app/scripts/actions/common/onChangeUtil.js +++ /dev/null @@ -1,48 +0,0 @@ -'use strict'; - -import updateFormField from './updateFormField'; - -/** - * This function is a generic `onChange` Handler. Typical use is as follows: - * - * ``` - * import onChange from 'this/file/here'; - * - * createClass({ - * _onChange: onChange({ storePrefix: 'ENTERPRISE_TRIAL' }), - * render() { - * return ( - * - * ) - * } - * }); - * ``` - * - * `function setComponentOnChangeHandler` is the one that is `bind`ed. - * - * storePrefix is `ENTERPRISE_TRIAL` in the stores handlers object: - * - * ``` - * handlers: { - * ENTERPRISE_TRIAL_CLEAR_FORM: '_clearForm', - * ENTERPRISE_TRIAL_UPDATE_FIELD_WITH_VALUE: '_updateFieldWithValue', - * ENTERPRISE_TRIAL_ATTEMPT_START: '_enterpriseTrialAttemptStart', - * ENTERPRISE_TRIAL_BAD_REQUEST: '_badRequest', - * ENTERPRISE_TRIAL_SUCCESS: '_enterpriseTrialSuccess' - * } - * ``` - * - * e is the onChange event from the form field. - */ - -export default function({ storePrefix }) { - return function setComponentOnChangeHandler(fieldKey) { - return (e) => { - this.context.executeAction(updateFormField({ storePrefix }), { - fieldKey, - fieldValue: e.target.value - }); - }; - }; -} - diff --git a/app/scripts/actions/common/updateFormField.js b/app/scripts/actions/common/updateFormField.js deleted file mode 100644 index 69eb40e138..0000000000 --- a/app/scripts/actions/common/updateFormField.js +++ /dev/null @@ -1,50 +0,0 @@ -'use strict'; - -/** - * This function dispatches an event that updates a form backed by a form store. - * @param {string} storePrefix - the prefix for the form store events. This - * scopes the event to a particular store. - * - * The storePrefix usually takes the form of a shortened version of the store's - * name. In the case of the `EnterpriseTrialFormStore`, given handlers as such: - * - * ``` - * handlers: { - * ENTERPRISE_TRIAL_UPDATE_FIELD_WITH_VALUE: 'updateFormField' - * } - * ``` - * - * The store prefix for the preceeding example is `ENTERPRISE_TRIAL`. - * - * --- - * - * Usage of this module in a component might look like: - * - * ``` - * import updateFormField from 'wherever'; - * - * - * var Whatever = createClass({ - * _onChange(fieldKey) { - * return (e) => { - * this.context.executeAction(updateFormField({ - * storePrefix: 'ENTERPRISE_TRIAL' - * }), { - * fieldKey, - * fieldValue: e.target.value - * }); - * } - * }, - * render() { - * return ( - * - * ) - * } - * }); - */ -export default function({storePrefix}){ - return (actionContext, { fieldKey, fieldValue}) => { - actionContext.dispatch(`${storePrefix}_UPDATE_FIELD_WITH_VALUE`, { fieldKey, fieldValue }); - }; -} - diff --git a/app/scripts/actions/common/validateBillingInfo.js b/app/scripts/actions/common/validateBillingInfo.js deleted file mode 100644 index 070f6eed95..0000000000 --- a/app/scripts/actions/common/validateBillingInfo.js +++ /dev/null @@ -1,7 +0,0 @@ -'use strict'; - -export default function({storePrefix}){ - return (actionContext, fieldErrors) => { - actionContext.dispatch(`${storePrefix}_ERRORS`, fieldErrors); - }; -} diff --git a/app/scripts/actions/convertToOrganization.js b/app/scripts/actions/convertToOrganization.js deleted file mode 100644 index 85a4ed4af5..0000000000 --- a/app/scripts/actions/convertToOrganization.js +++ /dev/null @@ -1,33 +0,0 @@ -'use strict'; - -import { Users } from 'hub-js-sdk'; -var debug = require('debug')('hub:actions:convertToOrganization'); - -module.exports = function(actionContext, {jwt, username, newOwner}, done) { - Users.convertToOrganization(jwt, username, newOwner, function(err, res) { - if (err) { - debug('error', err); - if (res.badRequest){ - let message; - if (res.body) { - message = res.body; - } else { - try { - message = JSON.parse(res.text); - } catch(e) { - message = { - error: 'Your account could not be converted. Make sure you are not a member of another group and that the new owner username exists' - }; - } - } - actionContext.dispatch('CONVERT_TO_ORG_BAD_REQUEST', message); - done(); - } else { - done(); - } - } else { - actionContext.history.push('/login/'); - actionContext.dispatch('LOGOUT', null); - } - }); -}; diff --git a/app/scripts/actions/createAutobuild.js b/app/scripts/actions/createAutobuild.js deleted file mode 100644 index 4daa9ee69d..0000000000 --- a/app/scripts/actions/createAutobuild.js +++ /dev/null @@ -1,97 +0,0 @@ -'use strict'; -import { Autobuilds } from 'hub-js-sdk'; -const getRepository = require('hub-js-sdk').Repositories.getRepo; -import async from 'async'; -import has from 'lodash/object/has'; -import omit from 'lodash/object/omit'; -const debug = require('debug')('hub:actions:createAutobuild'); - -/** - * - * @param actionContext - * @param jwt - * @param autobuildConfig - * {name, namespace, description, active, is_automated, - * provider, is_private, dockerfileLocation, sourceName, sourceType} - */ -export default function(actionContext, {JWT, autobuildConfig}) { - /** - * CreateAutoBuildSerializer { - * vcs_repo_name (string), - * provider (choice) = ['github' or 'bitbucket'], - * dockerhub_repo_name (string), - * is_private (boolean), - * build_tags (array[string]) - * description? - * } - * @param cb - * @private - */ - var _createAutobuild = function(cb) { - var bTags = autobuildConfig.tags; - for (var i = 0; i < bTags.length; ++i) { - bTags[i] = omit(bTags[i], 'id'); - } - var ab = { - name: autobuildConfig.name, - namespace: autobuildConfig.namespace, - description: autobuildConfig.description, - vcs_repo_name: autobuildConfig.build_name, - provider: autobuildConfig.provider, - dockerhub_repo_name: autobuildConfig.namespace + '/' + autobuildConfig.name, - is_private: autobuildConfig.is_private, - active: autobuildConfig.active, - build_tags: bTags - }; - Autobuilds.createAutomatedBuild(JWT, ab, function(err, res) { - if (err) { - debug('createAutomatedBuild error', err); - if (err.response.badRequest) { - //Check fields and set a better response for fields - const { detail } = err.response.body; - if(detail) { - actionContext.dispatch('AUTOBUILD_BAD_REQUEST', detail); - } - } else if (err.response.unauthorized) { - actionContext.dispatch('AUTOBUILD_UNAUTHORIZED', err); - } else if (err.response.serverError) { - actionContext.dispatch('AUTOBUILD_ERROR', err); - } - cb(err); - } else if (res.body) { - var repoUrl = res.body.docker_url; - actionContext.dispatch('AUTOBUILD_SUCCESS'); - cb(null, repoUrl); - } - }); - }; - - /** - * - * @param repoUrl something like arunan/d3 - * @param cb - * @private - */ - var _getRepository = function(repoUrl, cb) { - getRepository(JWT, repoUrl, function(err, res) { - if (err) { - debug('getRepository error', err); - actionContext.dispatch('GET_REPOSITORY_ERROR'); - cb(err); - } else if (res.body) { - cb(null, res.body); - } - }); - }; - - actionContext.dispatch('ATTEMPTING_AUTOBUILD_CREATION'); - async.waterfall([ - _createAutobuild, - _getRepository - ], function(err, result) { - if (!err) { - actionContext.dispatch('RECEIVE_REPOSITORY', result); - } - }); - -} diff --git a/app/scripts/actions/createNewLicenseProduction.js b/app/scripts/actions/createNewLicenseProduction.js deleted file mode 100644 index 4638e58142..0000000000 --- a/app/scripts/actions/createNewLicenseProduction.js +++ /dev/null @@ -1,82 +0,0 @@ -'use strict'; - -import { Billing } from 'hub-js-sdk'; -const debug = require('debug')('hub:actions:createNewLicenseProduction'); - -export default function(actionContext, { - address1, - address2, - city, - country, - cvv, - first_name, - JWT, - last_name, - month, - number, - package_name, - partnervalue, - postal_code, - state, - username, - year -}, done) { - actionContext.dispatch('ENTERPRISE_PAID_ATTEMPT_START'); - try { - /** - * This will only run where window is defined. ie: the browser - * It throws an exception in node - */ - window.recurly.configure(process.env.RECURLY_PUBLIC_KEY); - } catch(e) { - debug('error', e); - } - - var recurlyData = { - first_name, - last_name, - month, - year, - cvv, - number, - address1, - address2, - city, - country, - postal_code, - state - }; - - window.recurly.token(recurlyData, function(recurlyErr, token) { - if (recurlyErr) { - debug('recurly error', recurlyErr.fields); - actionContext.dispatch('ENTERPRISE_PAID_GET_RECURLY_ERROR', recurlyErr.fields); - done(); - } else { - debug('creating License'); - Billing.createLicense(JWT, { - username, - package: package_name, - payment_token: token.id, - first_name, - last_name, - postal_code, - partner_value: partnervalue - }, (err, results) => { - if(err) { - if(err.response.badRequest) { - const { detail } = err.response.body; - if(detail) { - actionContext.dispatch('ENTERPRISE_PAID_BAD_REQUEST', detail); - } - } else { - actionContext.dispatch('ENTERPRISE_PAID_API_ERROR'); - } - } else { - actionContext.dispatch('ENTERPRISE_PAID_CLEAR_FORM'); - actionContext.history.push('/account/licenses/'); - } - }); - } - }); -} diff --git a/app/scripts/actions/createNewLicenseTrial.js b/app/scripts/actions/createNewLicenseTrial.js deleted file mode 100644 index 09abbb3360..0000000000 --- a/app/scripts/actions/createNewLicenseTrial.js +++ /dev/null @@ -1,53 +0,0 @@ -'use strict'; - -import { Billing } from 'hub-js-sdk'; -const debug = require('debug')('hub:actions:createNewLicenseTrial'); - -export default function(actionContext, { - JWT, - companyName, - country, - email, - firstName, - jobFunction, - lastName, - namespace, - packageName, - phoneNumber, - state -}) { - actionContext.dispatch('ENTERPRISE_TRIAL_ATTEMPT_START'); - const licenseData = { - company_name: companyName, - country, - email, - first_name: firstName, - job_function: jobFunction, - last_name: lastName, - package: packageName, - phone_number: phoneNumber, - username: namespace - }; - - // state is an optional field - if(state) { - licenseData.state = state; - } - - Billing.createLicense(JWT, licenseData, (err, results) => { - if(err) { - debug('error', err); - if(err.response.badRequest) { - const { detail } = err.response.body; - if(detail) { - actionContext.dispatch('ENTERPRISE_TRIAL_BAD_REQUEST', detail); - } - } else { - actionContext.dispatch('ENTERPRISE_TRIAL_FACEPALM'); - } - } else { - actionContext.dispatch('ENTERPRISE_TRIAL_SUCCESS'); - actionContext.history.push(`/enterprise/trial/success/?namespace=${namespace}&step=1`); - } - }); -} diff --git a/app/scripts/actions/createOrgTeam.js b/app/scripts/actions/createOrgTeam.js deleted file mode 100644 index a5371050ff..0000000000 --- a/app/scripts/actions/createOrgTeam.js +++ /dev/null @@ -1,76 +0,0 @@ -'use strict'; -import { Orgs } from 'hub-js-sdk'; -import async from 'async'; -const debug = require('debug')('hub:actions:createOrgTeam'); - -module.exports = function(actionContext, {jwt, orgName, team}) { - - var _createTeam = function(cb) { - Orgs.createTeam(jwt, orgName, team, function(err, res) { - if (err) { - debug('createTeam error', err); - cb(err); - var errRes = err.response; - if (errRes.badRequest) { - actionContext.dispatch('TEAM_BAD_REQUEST', err); - } else if (errRes.unauthorized) { - actionContext.dispatch('TEAM_UNAUTHORIZED', err); - } else { - actionContext.dispatch('TEAM_ERROR', err); - } - } else { - if (res.body) { - //send team name to get members for the team - actionContext.dispatch('CREATE_ORG_TEAM', res.body); - actionContext.dispatch('RECEIVE_DASHBOARD_ORG_TEAM', res.body); - cb(null, res.body.name); - } - } - }); - }; - - var _getMembers = function(teamName, cb) { - Orgs.getMembers(jwt, orgName, teamName, function(err, res) { - if (err) { - debug('getMembers error', err); - cb(err); - } else { - actionContext.dispatch('RECEIVE_DASHBOARD_TEAM_MEMBERS', res.body); - cb(null, 'done'); - } - }); - }; - - var _createTeamWrapper = function(cb) { - async.waterfall([ - _createTeam, - _getMembers - ], function(err, res) { - cb(null, res); - } - ); - }; - - var _getTeamsForOrg = function(cb) { - Orgs.getTeams(jwt, orgName, function(err, res) { - if (err) { - debug('getTeams error', err); - cb(err); - } else { - if (res.body) { - cb(null, res.body); - } - } - }); - }; - - async.series([ - _createTeamWrapper, - _getTeamsForOrg - ], function(err, results) { - if (results[0] && results[1]) { - actionContext.dispatch('RECEIVE_DASHBOARD_ORG_TEAMS', results[1]); - actionContext.history.push(`/u/${orgName}/dashboard/teams/?team=${team.name}`); - } - }); -}; diff --git a/app/scripts/actions/createOrganization.js b/app/scripts/actions/createOrganization.js deleted file mode 100644 index 4e2e9d49bd..0000000000 --- a/app/scripts/actions/createOrganization.js +++ /dev/null @@ -1,65 +0,0 @@ -'use strict'; - -var debug = require('debug')('hub:actions:createOrganization'); -import async from 'async'; -import { Orgs, Users } from 'hub-js-sdk'; -//Organization Object -/* - { - id (string), - orgname (regex), - full_name (string), - location (string): Your Location on the world, - company (string): Your organization's name, - profile_url (url): Your place on the web, - gravatar_email (email): This address will define which picture of you is shown, - is_active (boolean): Designates whether user is active. Unselect this instead of deleting accounts., - date_joined (datetime), - gravatar_url (string) - } - */ -export default function(actionContext, {jwt, organization}) { - - var _createOrg = function(cb) { - Orgs.createOrg(jwt, organization, function(err, res) { - if (err) { - if(res && res.badRequest) { - debug('createOrg error', err); - actionContext.dispatch('ADD_ORG_BAD_REQUEST', res.body); - cb(err, res); - } else { - actionContext.dispatch('ADD_ORG_FACEPALM'); - cb(err, res); - } - } else { - cb(null, res.body); - } - }); - }; - - //Get orgs for user - var _getOrgsForUser = function(cb) { - Users.getOrgsForUser(jwt, function(err, res) { - if (err) { - debug('getOrgsForUser error', err); - cb(err, {}); - } else { - actionContext.dispatch('CURRENT_USER_ORGS', res.body.results); - cb(null, res.body.results); - } - }); - return {}; - }; - - async.series([ - _createOrg, - _getOrgsForUser - ], function (err, results) { - if(err) { - debug('final callback error', err); - } else { - actionContext.dispatch('CREATED_ORGANIZATION', {newOrg: results[0], userOrgs: results[1]}); - actionContext.history.push(`/u/${organization.orgname}/dashboard/teams/`); - } - }); -} diff --git a/app/scripts/actions/createRepository.js b/app/scripts/actions/createRepository.js deleted file mode 100644 index f2463a93dc..0000000000 --- a/app/scripts/actions/createRepository.js +++ /dev/null @@ -1,30 +0,0 @@ -/* @flow */ -'use strict'; - -var createRepo = require('hub-js-sdk').Repositories.createRepository; -var debug: Function = require('debug')('hub:actions:createRepository'); - -var createRepository = function(actionContext: {dispatch: Function}, - {jwt, repository}: {jwt: string; repository: any}) { - createRepo(jwt, repository, (err, res) => { - if (err) { - - if(res && res.badRequest) { - actionContext.dispatch('CREATE_REPO_BAD_REQUEST', res.body); - } else { - actionContext.dispatch('CREATE_REPO_ERROR', err); - } - - } else { - - if (res && res.ok) { - actionContext.dispatch('RECEIVE_REPOSITORY', res.body); - actionContext.dispatch('CREATE_REPO_CLEAR_FORM'); - actionContext.history.push(`/r/${repository.namespace}/${repository.name}/`); - } - - } - }); -}; - -module.exports = createRepository; diff --git a/app/scripts/actions/createSubscription.js b/app/scripts/actions/createSubscription.js deleted file mode 100644 index 1c817d3ab3..0000000000 --- a/app/scripts/actions/createSubscription.js +++ /dev/null @@ -1,374 +0,0 @@ -'use strict'; -const request = require('superagent'); -import { Billing } from 'hub-js-sdk'; -/*global UpdateBillingInfoPayload */ -import map from 'lodash/collection/map'; -import has from 'lodash/object/has'; -import merge from 'lodash/object/merge'; -import isString from 'lodash/lang/isString'; -import async from 'async'; -var debug = require('debug')('hub:actions:createBillingSubscription'); - -import _encodeForm from '../components/utils/encodeForm.js'; -import { - ACCOUNT, - BILLING, - BILLFORWARD_ACCOUNT_ID, - STRIPE_URL, - STRIPE_STAGE_TOKEN, - STRIPE_PROD_TOKEN, - BF_STAGE_URL, - BF_PROD_URL, - BF_STAGE_TOKEN, - BF_PROD_TOKEN, - v4BillingProfile -} from 'stores/common/Constants.js'; - -const handleResponse = ({ callback, dispatch, type }) => (err, res) => { - if (err) { - let message = 'There was an error creating your subscription. Please check your information and try again.'; - if (res && res.body) { - message = isString(res.body.detail) ? res.body.detail : res.body.message; - } - dispatch('BILLING_SUBMIT_ERROR', message); - callback(err, res); - } else if (res.ok) { - if (type === ACCOUNT) { - dispatch('BILLING_ACCOUNT_EXISTS'); - } else if (type === BILLING) { - dispatch('BILLING_INFO_EXISTS'); - } - const billforward_id = res.header[BILLFORWARD_ACCOUNT_ID]; - callback(null, { billforward_id }); - } -}; - -//-------------------------------------------------------------------------- -// CREATE A BILLING PAYMENT METHOD ON BILLFORWAD WITH STRIPE -//-------------------------------------------------------------------------- -/* - NOTE: Stripe's api only accepts x-www-form-urlencoded data - NOTE: 'billforwardCreatePayment' is chained to this function and requires - `billforward-id`. The `billforward-id` is being passed through to the - create payment function via the META here. -*/ -function _createCardToken({ - cvc, - exp_month, - exp_year, - name_first, - name_last, - number -}, cb) { - const stripeToken = process.env.ENV === 'production' ? - STRIPE_PROD_TOKEN : STRIPE_STAGE_TOKEN; - const card = { - name: `${name_first} ${name_last}`, - cvc, - number, - exp_month, - exp_year - }; - const encoded = _encodeForm({ card }); - request.post(STRIPE_URL) - .accept('application/json') - .type('application/x-www-form-urlencoded') - .set('Authorization', 'Bearer ' + stripeToken) - .send(encoded) - .end(cb); -} - -/* - NOTE: This is the call to billforward that actually adds a payment method - to a user's billing profile. - This call requires a billforward-id (accountID) which is DIFFERENT than the - docker_id - Hence why 'billingCreatePaymentMethod' is NOT being wrapped by - the getAccountFromNamespace decorator. -*/ -function _billforwardAddPaymentMethod({ - '@type': type, - accountID, - cardID, - defaultPaymentMethod, - gateway, - stripeToken -}, cb) { - const billforwardUrl = process.env.ENV === 'production' ? - BF_PROD_URL : BF_STAGE_URL; - const billforwardToken = process.env.ENV === 'production' ? - BF_PROD_TOKEN : BF_STAGE_TOKEN; - - request.post(billforwardUrl) - .accept('application/json') - .type('application/json') - .set('Authorization', 'Bearer ' + billforwardToken) - .send({ - '@type': type, - accountID, - cardID, - defaultPaymentMethod, - gateway, - stripeToken - }) - .end(cb); -} - -function billingStripeCreatePaymentMethod(dispatch, { - billforward_id, - cvc, - exp_month, - exp_year, - name_first, - name_last, - number -}, cb) { - const cardData = { - cvc, - exp_month, - exp_year, - name_first, - name_last, - number - }; - /* - NOTE: - Creating a payment method requires 2 parts - 1 - Generating a token from Stripe's api - 2 - Sending generated token to Billforward's api to attach payment method to - a relevant billing profile. - */ - _createCardToken(cardData, (stripeErr, stripeRes) => { - if (!stripeRes.ok) { - let message = 'There was an error submitting your card information. Please check your information and try again.'; - if (stripeRes.error && stripeRes.error.message) { - message = stripeRes.error.message; - } - dispatch('BILLING_SUBMIT_ERROR', message); - cb(message); - } else { - const tokenObject = stripeRes && stripeRes.body; - const stripeToken = tokenObject.id; - const cardID = tokenObject.card.id; - const accountID = billforward_id; - const bfData = { - '@type': 'StripeAuthCaptureRequest', - accountID, - cardID, - defaultPaymentMethod: true, - gateway: 'Stripe', - stripeToken - }; - _billforwardAddPaymentMethod(bfData, handleResponse({ callback: cb, dispatch, type: BILLING })); - } - }); -} - -//-------------------------------------------------------------------------- -// SAVE ADDRESS INFORMATION IN BILLFORWARD -//-------------------------------------------------------------------------- -const updateV4BillingProfile = ({ JWT, profileData, docker_id }, cb) => { - const v4BillingAPI = v4BillingProfile(docker_id); - request - .patch(v4BillingAPI) - .accept('application/json') - .type('application/json') - .set('Authorization', 'Bearer ' + JWT) - .send(profileData) - .end(cb); -}; - -//-------------------------------------------------------------------------- -// CREATE NEW BILLING ACCOUNT/PROFILE & SUBSCRIPTION -//-------------------------------------------------------------------------- -function createSubscription(actionContext, { - JWT, - user, - accountInfo, - billingInfo, - card, - isNewBillingAccount, - billforwardId: existingBfId, - plan_code, - package_code -}, done) { - actionContext.dispatch('BILLING_SUBMIT_START'); - const { - first_name, - last_name, - address1, - address2, - country, - state, - zip, - city - } = billingInfo; - const { - number, - cvv, - month, - year, - last_four, - type, - coupon_code, - coupon - } = card; - - let isOrg = false; - let username = ''; - if (has(user, 'username')) { - username = user.username; - } else if (has(user, 'orgname')) { - username = user.orgname; - isOrg = true; - } - - var subscriptionData = { - first_name, - last_name, - email: accountInfo.email, - username, - plan: plan_code, - package: package_code - }; - if (coupon_code) { - // coupon code is an optional field - subscriptionData.coupon_code = coupon_code; - } - - async.waterfall([ - function(callback) { // create billing profile - const account = merge({}, accountInfo, {username}); - /* - NOTE: - Can only get to this action IF - 1) You don't have a billing profile account (Create the billing account) - 2) You don't have any billing payment information - but you have a billing profile account (Update the account) - */ - if (isNewBillingAccount) { - Billing.createBillingAccount(JWT, account, handleResponse({callback, dispatch: actionContext.dispatch, type: ACCOUNT})); - // on success - callback(null, { billforward_id }) - } else { - Billing.updateBillingAccount(JWT, username, account, handleResponse({callback, dispatch: actionContext.dispatch, type: ACCOUNT})); - } - }, - function({ billforward_id }, callback) { - const bfId = billforward_id || existingBfId; - if (bfId) { - // NOTE: Save billing address information - const profileData = { - first_name, - last_name, - addresses: [ - { - address_line_1: address1, - address_line_2: address2, - city, - province: state, - country, - post_code: zip, - primary_address: true - } - ] - }; - updateV4BillingProfile({ - JWT, - profileData, - docker_id: user.id - }, (err, res) => { - if (err) { - let message = 'There was an error saving your address information. Please check your information and try again.'; - if (res && res.body) { - message = isString(res.body.detail) ? res.body.detail : res.body.message; - } - actionContext.dispatch('BILLING_SUBMIT_ERROR', message); - callback(null); - return; - } - callback(null, {...res.body, billforward_id }); - }); - return; - } - // NOTE: Unecessary for non-migrated accounts - Creation of billingprofile will update the account data - callback(null, { billforward_id }); - }, - function({ billforward_id }, callback) { - const bfId = billforward_id || existingBfId; - if (bfId) { - // NOTE: If we have a billforward id - create payment Method via stripe - billingStripeCreatePaymentMethod(actionContext.dispatch, { - billforward_id: bfId, - cvc: cvv, - exp_month: month, - exp_year: year, - name_first: first_name, - name_last: last_name, - number - }, callback); - return; - } - // NOTE: If we do NOT have a billforward id - tokenize via recurly - const recurlyData = { - first_name, - last_name, - address1, - address2, - country, - state, - zip, - city, - number, - cvv, - month, - year, - coupon_code - }; - try { - /** - * This will only run where window is defined. ie: the browser - * It throws an exception in node - */ - window.recurly.configure(process.env.RECURLY_PUBLIC_KEY); - } catch(e) { - debug('error', e); - } - window.recurly.token(recurlyData, function(recurlyErr, token) { - if (recurlyErr) { - debug('recurly token error', recurlyErr.message); - actionContext.dispatch('GET_RECURLY_ERROR', recurlyErr); - callback(recurlyErr); - return; - } - callback(null, { recurlyToken: token.id }); - }); - }, - function({ recurlyToken }, callback) { - // NOTE: append the recurly token to the subscriptionData object; - subscriptionData.payment_token = recurlyToken; - /* - NOTE: Creating billing subscription will either - A) Use default card if billing account is migrated and we get a billforward id - B) Subscription Data will have a recurly token if no billforward id - IF Billing Info already exists: - - Stripe: Adds a new default card - - Recurly: we're posting with the recurly token which will update it - */ - Billing.createBillingSubscription(JWT, subscriptionData, handleResponse({callback, dispatch: actionContext.dispatch, type: BILLING})); - } - ], - function(err, res) { - if (err) { - debug(err); - done(); - } else { - if (isOrg) { - actionContext.history.push(`/u/${username}/dashboard/billing/`); - } else { - actionContext.history.push('/account/billing-plans/'); - } - actionContext.dispatch('BILLING_SUBMIT_SUCCESS'); - done(); - } - }); -} - -module.exports = createSubscription; diff --git a/app/scripts/actions/createTeamMembers.js b/app/scripts/actions/createTeamMembers.js deleted file mode 100644 index eee9225bad..0000000000 --- a/app/scripts/actions/createTeamMembers.js +++ /dev/null @@ -1,66 +0,0 @@ -'use strict'; - -var debug = require('debug')('hub:actions:createTeamMembers'); -import async from 'async'; -import { Orgs } from 'hub-js-sdk'; - -export default function(actionContext, {jwt, orgname, teamname, members}) { - - var _createMember = function(cb) { - var _makeMemberFuncArray = function(member) { - return function() { - // member.username can be either a valid email or a username - Orgs.createMember(jwt, orgname, teamname, member.username, function(err, res) { - if (err) { - debug('createMember error', err); - if (res.badRequest) { - actionContext.dispatch('TEAM_MEMBER_BAD_REQUEST', err); - } else if (res.unauthorized) { - actionContext.dispatch('TEAM_MEMBER_UNAUTHORIZED', err); - } else { - actionContext.dispatch('TEAM_MEMBER_ERROR', err); - } - } else { - if (res.ok) { - actionContext.dispatch('ORG_TEAM_CLEAR_ERROR_STATES'); - cb(null, res.body); - } - } - }); - }; - }; - var funcArray = []; - for(var i = 0; i < members.length; ++i) { - funcArray.push(_makeMemberFuncArray(members[i])); - } - async.parallel(funcArray, function(err, results) { - if (err) { - cb(err); - } else { - cb(null, results); - } - }); - }; - - //Get members for team - var _getMembersForTeam = function(cb) { - Orgs.getMembers(jwt, orgname, teamname, function(err, res) { - if (err) { - debug('getMembers error', err); - cb(err, {}); - } else { - actionContext.dispatch('RECEIVE_DASHBOARD_TEAM_MEMBERS', res.body); - cb(null, res.body.results); - } - }); - }; - - async.series([ - _createMember, - _getMembersForTeam - ], function (err, results) { - if(err) { - debug('final callback error', err); - } - }); -} diff --git a/app/scripts/actions/createWebhook.js b/app/scripts/actions/createWebhook.js deleted file mode 100644 index 0915fe4f11..0000000000 --- a/app/scripts/actions/createWebhook.js +++ /dev/null @@ -1,27 +0,0 @@ -'use strict'; -import async from 'async'; -import request from 'superagent'; -const debug = require('debug')('createWebhook'); - -// TODO: REMOVE. This is deprecated in favor of AddPipeline -module.exports = function(actionContext, { JWT, namespace, name, webhookName }) { - - request.post(`${process.env.REGISTRY_API_BASE_URL}/v2/repositories/${namespace}/${name}/webhooks/`) - .accept('application/json') - .set('Authorization', `JWT ${JWT}`) - .send({ - name: webhookName - }) - .end((err, results) => { - if(err) { - debug(err); - if(err.response.badRequest) { - debug('badrequest'); - } else { - debug('facepalm'); - } - } else { - actionContext.history.push(`/r/${namespace}/${name}/~/settings/webhooks/`); - } - }); -}; diff --git a/app/scripts/actions/delCollaborator.js b/app/scripts/actions/delCollaborator.js deleted file mode 100644 index 3ffce1abb2..0000000000 --- a/app/scripts/actions/delCollaborator.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; -import { - Repositories as R - } from 'hub-js-sdk'; - -export default function delCollaborator(actionContext, { JWT, namespace, name, username }, done) { - actionContext.dispatch('DEL_COLLABORATORS_SET_LOADING', username); - R.delCollaborator(JWT, { namespace, name, username }, (err, res) => { - if(err) { - actionContext.dispatch('DEL_COLLABORATORS_SET_ERROR', username); - } else { - actionContext.dispatch('DEL_COLLABORATORS_SET_SUCCESS', username); - R.getCollaboratorsForRepo(JWT, `${namespace}/${name}`, (getErr, getRes) => { - if(getErr) { - // 'Org repositories do not have collaborators.' - actionContext.dispatch('COLLAB_RECEIVE_COLLABORATORS', {}); - } else { - actionContext.dispatch('COLLAB_RECEIVE_COLLABORATORS', getRes.body); - } - }); - } - done(); - }); -} diff --git a/app/scripts/actions/delTeamCollaborator.js b/app/scripts/actions/delTeamCollaborator.js deleted file mode 100644 index cda330a123..0000000000 --- a/app/scripts/actions/delTeamCollaborator.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; -import { - Repositories as R - } from 'hub-js-sdk'; - -export default function delCollaborator(actionContext, { JWT, namespace, name, group_id }, done) { - actionContext.dispatch('DEL_COLLABORATORS_SET_LOADING', group_id); - R.delTeamCollaborator(JWT, { namespace, name, group_id }, (err, res) => { - if(err) { - actionContext.dispatch('DEL_COLLABORATORS_SET_ERROR', group_id); - } else { - actionContext.dispatch('DEL_COLLABORATORS_SET_SUCCESS', group_id); - R.getTeamCollaboratorsForRepo(JWT, `${namespace}/${name}`, (getErr, getRes) => { - if (getErr) { - // 'User repository does not have any teams yet' - actionContext.dispatch('COLLAB_RECEIVE_TEAMS', {}); - } else { - actionContext.dispatch('COLLAB_RECEIVE_TEAMS', getRes.body); - } - }); - } - done(); - }); -} diff --git a/app/scripts/actions/deleteAutoBuildPushTriggerItem.js b/app/scripts/actions/deleteAutoBuildPushTriggerItem.js deleted file mode 100644 index e3ff3c61bb..0000000000 --- a/app/scripts/actions/deleteAutoBuildPushTriggerItem.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict'; - -var debug = require('debug')('hub:actions:deleteAutoBuildPushTriggerItem'); - -export default function(actionContext, {isNew, index}) { - if (isNew) { - actionContext.dispatch('DELETE_AUTOBUILD_NEW_TAG_ITEM', index); - } else { - actionContext.dispatch('DELETE_AUTOBUILD_PUSH_TRIGGER_ITEM', index); - } -} diff --git a/app/scripts/actions/deleteEmail.js b/app/scripts/actions/deleteEmail.js deleted file mode 100644 index aa8db4b2f0..0000000000 --- a/app/scripts/actions/deleteEmail.js +++ /dev/null @@ -1,38 +0,0 @@ -'use strict'; - -import sortByOrder from 'lodash/collection/sortByOrder'; -import { series, each } from 'async'; -import { - Emails - } from 'hub-js-sdk'; -var debug = require('debug')('hub:actions:deleteEmail'); - -function updateEmailSettings({ dispatch }, - {JWT, delEmailID, username}, - done) { - dispatch('START_SAVE_ACTION'); - Emails.deleteEmailByID(JWT, - delEmailID, - (err, res) => { - if (err) { - return debug('deleteEmailByID error', err); - } - Emails.getEmailsForUser(JWT, username, function(emailErr, emailRes){ - if (emailErr) { - debug('getEmailsForUser error', emailErr); - dispatch('FINISH_SAVE_ACTION'); - return done(); - } - var emails = emailRes.body.results; - var sortedEmails = sortByOrder(emails, - ['primary', 'verified'], - [false, false]); - dispatch('RECEIVE_EMAILS', { - emails: sortedEmails - }); - dispatch('FINISH_SAVE_ACTION'); - }); - }); -} - -module.exports = updateEmailSettings; diff --git a/app/scripts/actions/deleteEmailNotifs.js b/app/scripts/actions/deleteEmailNotifs.js deleted file mode 100644 index 3cae021514..0000000000 --- a/app/scripts/actions/deleteEmailNotifs.js +++ /dev/null @@ -1,46 +0,0 @@ -'use strict'; - -var debug = require('debug')('hub:actions:deleteEmailNotifs'); -import async from 'async'; - -import { Notifications } from 'hub-js-sdk'; - -var deleteEmailNotifs = function(actionContext, {jwt, notificationID}) { - var _delNotificationSettings = function(cb) { - Notifications.deleteNotificationSubscription(jwt, notificationID, function(err, res) { - if (err) { - debug('deleteNotificationSubscription error', err); - cb(err); - } else if (res.ok) {//TODO:Weird that 204 no content is sent on success - return cb(null, res); - } - }); - }; - - var _getNotificationSettings = function(cb) { - //all good, do the next call to get the notifications - Notifications.getNotificationSubscriptions(jwt, function(err, res) { - if (err) { - debug('getNotificationSubscriptions error', err); - cb(err); - } else { - cb(null, res.body.results); - } - }); - }; - - async.series([ - _delNotificationSettings, - _getNotificationSettings - ], function (err, results) { - if (err) { - actionContext.dispatch('SAVE_NOTIFICATIONS_ERROR'); - debug('final callback error', err); - } else if (results[1]) { - actionContext.dispatch('SAVE_NOTIFICATIONS_SUCCESS'); - actionContext.dispatch('RECEIVE_NOTIFICATIONS', results[1]); - } - }); -}; - -module.exports = deleteEmailNotifs; diff --git a/app/scripts/actions/deletePipeline.js b/app/scripts/actions/deletePipeline.js deleted file mode 100644 index e04e8be1cb..0000000000 --- a/app/scripts/actions/deletePipeline.js +++ /dev/null @@ -1,25 +0,0 @@ -'use strict'; - -import request from 'superagent'; - -export default function deletePipeline({ - dispatch, history -}, { - jwt, namespace, name, slug -}, done) { - dispatch('DELETE_PIPELINE_ATTEMPTING'); - request.del(`${process.env.HUB_API_BASE_URL}/v2/repositories/${namespace}/${name}/webhook_pipeline/${slug}/`) - .set('Authorization', `JWT ${jwt}`) - .type('json') - .accept('json') - .end((err, res) => { - if(err) { - dispatch('DELETE_PIPELINE_FACEPALM'); - done(); - } else { - dispatch('DELETE_PIPELINE_SUCCESS'); - history.push(`/r/${namespace}/${name}/~/settings/webhooks/`); - done(); - } - }); -} diff --git a/app/scripts/actions/deleteRepo.js b/app/scripts/actions/deleteRepo.js deleted file mode 100644 index 7f44b65c9e..0000000000 --- a/app/scripts/actions/deleteRepo.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; - -import { Repositories as Repos } from 'hub-js-sdk'; -const debug = require('debug')('hub:actions:deleteRepo'); - -export default function(actionContext, {jwt, repoShortName}) { - actionContext.dispatch('DELETE_REPO_ATTEMPT_START'); - Repos.deleteRepository(jwt, repoShortName, (err, res) => { - if (err) { - const { badRequest, body } = err.response; - if(badRequest) { - actionContext.dispatch('DELETE_REPO_BAD_REQUEST', body); - } else { - actionContext.dispatch('DELETE_REPO_ERROR', err); - } - } else { - if (res && res.ok) { - actionContext.history.push('/'); - } - } - }); -} diff --git a/app/scripts/actions/deleteRepoComment.js b/app/scripts/actions/deleteRepoComment.js deleted file mode 100644 index 14b6c5e39d..0000000000 --- a/app/scripts/actions/deleteRepoComment.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; - -var debug = require('debug')('hub:actions:deleteRepoComment'); - -import { Repositories } from 'hub-js-sdk'; - -var deleteRepoComment = function(actionContext, {jwt, repoShortName, commentid}) { - Repositories.deleteRepoComment(jwt, repoShortName, commentid, function(delErr, delRes) { - if (delErr) { - debug('deleteRepoComment error', delErr); - } else if (delRes.ok) { - Repositories.getCommentsForRepo(jwt, repoShortName, function(getErr, getRes) { - if (getErr) { - debug('getCommentsForRepo error', getErr); - } else { - actionContext.dispatch('RECEIVE_REPO_COMMENTS', getRes.body); - } - }); - } - }); - -}; - -module.exports = deleteRepoComment; diff --git a/app/scripts/actions/downloadInvoice.js b/app/scripts/actions/downloadInvoice.js deleted file mode 100644 index edbd33b746..0000000000 --- a/app/scripts/actions/downloadInvoice.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; -// Blob is a polyfill -require('vendor/Blob'); -import { saveAs } from 'vendor/FileSaver'; - -const debug = require('debug')('hub:actions:downloadInvoice'); - -module.exports = function(actionContext, { JWT, username, invoiceId }) { - const xhr = new XMLHttpRequest(); - xhr.open('GET', process.env.REGISTRY_API_BASE_URL + '/api/billing/v3/account/' + username + '/invoices/' + invoiceId + '/'); - xhr.setRequestHeader('Authorization', 'JWT ' + JWT); - xhr.responseType = 'blob'; - xhr.onload = function() { - if (xhr.status === 200) { - const blob = new Blob([xhr.response], { - type: 'application/pdf' - }); - saveAs(blob, 'docker_invoice_' + invoiceId + '.pdf'); - } else { - debug('error'); - } - }; - xhr.send(); -}; diff --git a/app/scripts/actions/downloadLicenseContent.js b/app/scripts/actions/downloadLicenseContent.js deleted file mode 100644 index fb823166d0..0000000000 --- a/app/scripts/actions/downloadLicenseContent.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict'; - -const debug = require('debug')('hub:actions:downloadLicenseContent'); -import { Billing } from 'hub-js-sdk'; -// Blob is a polyfill -require('vendor/Blob'); -import { saveAs } from 'vendor/FileSaver'; - -export default function downloadLicenseContent(actionContext, { jwt, namespace, keyId }) { - actionContext.dispatch('ATTEMPTING_LICENSE_DOWNLOAD_START'); - Billing.getLicenseDownloadContent(jwt, { keyId, namespace }, (err, res) => { - if (err) { - debug('error', err); - if(err.response.badRequest) { - const { detail } = err.response.body; - if(detail) { - actionContext.dispatch('DOWNLOAD_LICENSE_CONTENT_BAD_REQUEST', detail); - } - } else { - actionContext.dispatch('DOWNLOAD_LICENSE_CONTENT_FACEPALM'); - } - } else { - actionContext.dispatch('RECEIVE_LICENSE_DOWNLOAD_CONTENT'); - //perform download as result of clicking download button - const blob = new Blob([res.text], { - type: 'text/plain;charset=utf-8' - }); - saveAs(blob, `docker_subscription.lic`); - } - }); -} diff --git a/app/scripts/actions/enterpriseAttemptLogin.js b/app/scripts/actions/enterpriseAttemptLogin.js deleted file mode 100644 index f8bbaa055d..0000000000 --- a/app/scripts/actions/enterpriseAttemptLogin.js +++ /dev/null @@ -1,155 +0,0 @@ -'use strict'; - -import { parallel, waterfall } from 'async'; -import sortBy from 'lodash/collection/sortBy'; -import { Auth, - Repositories as Repos, - Billing - } from 'hub-js-sdk'; -var debug = require('debug')('hub:actions:enterpriseAttemptLogin'); -import { getActivityFeed } from 'hub-js-sdk/src/Hub/SDK/Notifications'; -import { getUser } from 'hub-js-sdk/src/Hub/SDK/JWT'; -import { - getNamespacesForUser -} from 'hub-js-sdk/src/Hub/SDK/Users'; -import { getToken } from 'hub-js-sdk/src/Hub/SDK/Auth'; -import request from 'superagent'; - -//Get orgs for user -function _getOrgsForCurrentUser({jwt, username, dispatch}) { - return function(user, cb) { - getNamespacesForUser(jwt, function(err, res) { - if (err) { - debug('getNamespacesForUser', err); - cb(null); - } else { - // brute force the namespace reception so we can use a single action for now - dispatch('ENTERPRISE_TRIAL_RECEIVE_ORGS', res.body.namespaces); - dispatch('ENTERPRISE_PAID_RECEIVE_ORGS', res.body.namespaces); - cb(null, user); - } - }); - }; -} - -function _getBillingPlans({jwt, dispatch}) { - return function(user, cb) { - Billing.getPlans(jwt, 'personal', (err, res) => { - if(err) { - debug('getPlans error', err); - cb(null); - } else { - let plansList = res.body; - let sortedPlans = sortBy(plansList, 'display_order'); - dispatch('RECEIVE_BILLING_PLANS', { - plansList: sortedPlans - }); - cb(null, user); - } - }); - }; -} -function _getBillingAccount({jwt, dispatch}) { - return function(user, cb) { - Billing.getBillingAccount(jwt, user.username, (err, res) => { - if(err) { - debug('no billing account connected'); - cb(err, {}); - } else { - dispatch('RECEIVE_BILLING_INFO', { - accountInfo: res.body - }); - cb(null, user); - } - }); - }; -} - -function _getBillingInfo({jwt, dispatch}) { - return (user, cb) => { - Billing.getBillingInfo(jwt, user.username, (err, res) => { - if(err) { - debug('no billing account connected'); - cb(err, {}); - } else { - dispatch('RECEIVE_BILLING_INFO', { - billingInfo: res.body - }); - cb(null, user); - } - }); - }; -} - - -function handleGetUserInfo({jwt, username, dispatch}, callback) { - waterfall([ - function(cb){ - getUser(jwt, function(err, res) { - if (err) { - cb(err, {}); - } else { - dispatch('RECEIVE_USER', res.body); //LOGIN USING JWT.getUser - cb(null, res.body); - } - }); - }, - _getOrgsForCurrentUser({jwt, username, dispatch}), - _getBillingPlans({jwt, dispatch}), - _getBillingAccount({jwt, dispatch}), - _getBillingInfo({jwt, dispatch}) //Waterfalling the user through each call. - ], function(err, user) { - callback(err, { user }); - }); -} - -module.exports = function({ dispatch }, - { username, password }, - done) { - dispatch('LOGIN_ATTEMPT_START'); - getToken(username, - password, - function(err, res) { - if (err) { - debug('getToken error', err); - if (res.unauthorized) { - if(res.body && res.body.detail) { - /** - * This can happen if the user has not verified their email - */ - dispatch('LOGIN_UNAUTHORIZED_DETAIL', res.body); - } else { - dispatch('LOGIN_UNAUTHORIZED'); - } - } else if (res.badRequest){ - try { - dispatch('LOGIN_BAD_REQUEST', JSON.parse(res.text)); - } catch (error) { - dispatch('LOGIN_ERROR'); - } - } else { - // unhandled login error - dispatch('LOGIN_ERROR'); - } - } else { - if (res.body.token) { - request.post('/attempt-login/') - .send({jwt: res.body.token}) - .end((cookieErr, cookieRes) => { - handleGetUserInfo({ - jwt: res.body.token, - username, - dispatch - }, function(userErr, userRes) { - /** - * CreateBillingSubscription requires having allPlans - * If loggedOut and JWT is populated first, it will attempt to populate form, BEFORE plans have been dispatched - */ - dispatch('RECEIVE_JWT', res.body.token); - dispatch('LOGIN_CLEAR'); - }); - }); - } - } - }); -}; diff --git a/app/scripts/actions/forgotPasswordSubmit.js b/app/scripts/actions/forgotPasswordSubmit.js deleted file mode 100644 index ae953cbe3a..0000000000 --- a/app/scripts/actions/forgotPasswordSubmit.js +++ /dev/null @@ -1,18 +0,0 @@ -/* @flow */ -'use strict'; -import { - Users - } from 'hub-js-sdk'; -const debug = require('debug')('hub:actions:forgotPasswordSubmit'); - -var forgotPasswordSubmit = function(actionContext:{ dispatch : Function }, { email }) { - Users.forgotPassword(email, function(err, res) { - if (err) { - debug('forgotPassword error', err); - } else { - actionContext.dispatch('FORGOT_PASSWORD_SENT', res.body); - } - }); -}; - -module.exports = forgotPasswordSubmit; diff --git a/app/scripts/actions/getAllReposForFiltering.js b/app/scripts/actions/getAllReposForFiltering.js deleted file mode 100644 index 84b6662d0c..0000000000 --- a/app/scripts/actions/getAllReposForFiltering.js +++ /dev/null @@ -1,40 +0,0 @@ -'use strict'; -var debug = require('debug')('hub:actions:getAllReposForFiltering'); -import async from 'async'; -import isArray from 'lodash/lang/isArray'; -import { - Repositories as Repos -} from 'hub-js-sdk'; - -export default function getAllReposForFiltering(actionContext, {jwt, user}) { - - actionContext.dispatch('DASHBOARD_REPOS_STORE_ATTEMPTING_GET_ALL_REPOS'); - var _getAllRepos = function (cb) { - Repos.getAllReposForUser(jwt, user, function (err, res) { - if (err) { - cb(err); - } else { - cb(null, isArray(res.body) && res.body.length); - } - }); - }; - - //Get repos for user or org - var _getReposForUserOrOrg = function (pageSize, cb) { - Repos.getReposForUser(jwt, user, function (err, res) { - if (err) { - actionContext.dispatch('ERROR_RECEIVING_REPOS', err); - cb(); - } else { - actionContext.dispatch('DASHBOARD_REPOS_STORE_RECEIVE_ALL_REPOS_SUCCESS', res.body); - cb(); - } - }, 1, pageSize); - }; - - async.waterfall([ - _getAllRepos, - _getReposForUserOrOrg - ], function(error, response) { - }); -} diff --git a/app/scripts/actions/getPipelineHistory.js b/app/scripts/actions/getPipelineHistory.js deleted file mode 100644 index a1beeb9292..0000000000 --- a/app/scripts/actions/getPipelineHistory.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; - -import request from 'superagent'; - -export default function getPipelineHistory({ - dispatch, history -}, { - jwt, namespace, name, slug -}, done) { - request.get(`${process.env.HUB_API_BASE_URL}/v2/repositories/${namespace}/${name}/webhook_pipeline/${slug}/history/`) - .set('Authorization', `JWT ${jwt}`) - .type('json') - .accept('json') - .end((err, res) => { - if (err) { - return done(); - } else { - dispatch('RECEIVE_PIPELINE_HISTORY', {slug, payload: res.body}); - return done(); - } - }); -} diff --git a/app/scripts/actions/getRepoComments.js b/app/scripts/actions/getRepoComments.js deleted file mode 100644 index d87ee52987..0000000000 --- a/app/scripts/actions/getRepoComments.js +++ /dev/null @@ -1,23 +0,0 @@ -'use strict'; - -import _ from 'lodash'; -import { - Repositories as Repos - } from 'hub-js-sdk'; - -export default function repoComments(actionContext, payload) { - var token = payload.JWT; - - var namespace = payload.namespace; - if(payload.namespace === '_') { - namespace = 'library'; - } - var repoShortName = namespace + '/' + payload.repoName; - Repos.getCommentsForRepo(token, repoShortName, function(err, res) { - if (err) { - actionContext.dispatch('ERROR_RECEIVING_REPO_COMMENTS'); - } else { - actionContext.dispatch('RECEIVE_REPO_COMMENTS', res.body); - } - }, payload.pageNumber); -} diff --git a/app/scripts/actions/getSettingsData.js b/app/scripts/actions/getSettingsData.js deleted file mode 100644 index d8ae3fcf88..0000000000 --- a/app/scripts/actions/getSettingsData.js +++ /dev/null @@ -1,28 +0,0 @@ -'use strict'; -import _ from 'lodash'; -import { - Users - } from 'hub-js-sdk'; -var debug = require('debug')('hub:actions:getSettingsData'); - -var getSettingsData = function(actionContext, {JWT, username, repoType}) { - Users.getUserSettings(JWT, username, function(err, res) { - if (err){ - debug('getUserSettings', err); - } else { - if (repoType === 'regular') { - actionContext.dispatch('CREATE_REPO_UPDATE_FIELD_WITH_VALUE', { - fieldKey: 'is_private', - fieldValue: res.body.default_repo_visibility - }); - } else if (repoType === 'autobuild') { - actionContext.dispatch('AUTOBUILD_FORM_UPDATE_FIELD_WITH_VALUE', { - fieldKey: 'isPrivate', - fieldValue: res.body.default_repo_visibility - }); - } - } - }); -}; - -module.exports = getSettingsData; diff --git a/app/scripts/actions/getTeamMembers.js b/app/scripts/actions/getTeamMembers.js deleted file mode 100644 index 9a88acb6a7..0000000000 --- a/app/scripts/actions/getTeamMembers.js +++ /dev/null @@ -1,17 +0,0 @@ -'use strict'; - -import _ from 'lodash'; -import { - Orgs - } from 'hub-js-sdk'; -var debug = require('debug')('hub:actions:getTeamMembers'); - -export default function(actionContext, {jwt, orgname, teamname}) { - Orgs.getMembers(jwt, orgname, teamname, function (err, res) { - if (err) { - debug('error', err); - } else { - actionContext.dispatch('RECEIVE_TEAM_MEMBERS', res.body); - } - }); -} diff --git a/app/scripts/actions/githubOauth.js b/app/scripts/actions/githubOauth.js deleted file mode 100644 index fada58ae49..0000000000 --- a/app/scripts/actions/githubOauth.js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict'; - -const debug = require('debug')('hub:actions:githubOauth'); -const _ = require('lodash'); -const request = require('superagent'); - -module.exports = function(actionContext, {stateString}) { - request.post('/oauth/github-attempt/') - .send( {ghk: stateString} ) - .end(function(err, res) { - }); -}; diff --git a/app/scripts/actions/linkBitbucket.js b/app/scripts/actions/linkBitbucket.js deleted file mode 100644 index ab634d805a..0000000000 --- a/app/scripts/actions/linkBitbucket.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; - -import { Builds } from 'hub-js-sdk'; -const debug = require('debug')('hub:actions:linkBitbucket'); - -module.exports = function(actionContext, jwt) { - Builds.getBitbucketAuthUrl(jwt, function(err, res) { - if (err) { - debug('error', err); - actionContext.dispatch('BITBUCKET_AUTH_URL_ERROR', err); - } else if (res.ok) { - actionContext.dispatch('RECEIVE_BITBUCKET_AUTH_URL', res.body); - } - }); -}; diff --git a/app/scripts/actions/linkGithub.js b/app/scripts/actions/linkGithub.js deleted file mode 100644 index 2e410330f9..0000000000 --- a/app/scripts/actions/linkGithub.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; - -import { Builds } from 'hub-js-sdk'; -const debug = require('debug')('hub:actions:linkGithub'); - -module.exports = function(actionContext, jwt) { - Builds.getGithubClientID(jwt, function(err, res) { - if (err) { - debug('error', err); - actionContext.dispatch('GITHUB_ID_ERROR', err); - } else if (res.ok) { - actionContext.dispatch('RECEIVE_GITHUB_ID', res.body); - } - }); -}; diff --git a/app/scripts/actions/loginUpdateFormField.js b/app/scripts/actions/loginUpdateFormField.js deleted file mode 100644 index d2a993ac58..0000000000 --- a/app/scripts/actions/loginUpdateFormField.js +++ /dev/null @@ -1,7 +0,0 @@ -'use strict'; - -export default function({ dispatch }, - { fieldKey, fieldValue }, - done) { - dispatch('LOGIN_UPDATE_FIELD_WITH_VALUE', { fieldKey, fieldValue }); -} diff --git a/app/scripts/actions/logout.js b/app/scripts/actions/logout.js deleted file mode 100644 index abf325ae5a..0000000000 --- a/app/scripts/actions/logout.js +++ /dev/null @@ -1,29 +0,0 @@ -/* @flow */ -'use strict'; - -import type FluxibleActionContext from '../../../flow-libs/fluxible'; - -import { Auth } from 'hub-js-sdk'; -import request from 'superagent'; -import async from 'async'; -const debug = require('debug')('hub:actions:logout'); - -module.exports = function(actionContext: FluxibleActionContext, jwt) { - async.parallel([ - function(callback) { - Auth.logout(jwt, function(err, res) { - if (err) { - debug('error', err); - actionContext.dispatch('LOGOUT_ERROR', err); - } else if (res.ok) { - actionContext.dispatch('LOGOUT'); - actionContext.history.push('/'); - } - }); - }, - function(callback) { - request.post('/attempt-logout/') - .end(callback); - }], - function(err, results) {}); -}; diff --git a/app/scripts/actions/longDescriptionUpdateFormField.js b/app/scripts/actions/longDescriptionUpdateFormField.js deleted file mode 100644 index f3cad471e7..0000000000 --- a/app/scripts/actions/longDescriptionUpdateFormField.js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict'; - -export default function({ dispatch }, - { - fieldKey, - fieldValue - }, - done) { - dispatch('LONG_DESCRIPTION_UPDATE_FIELD_WITH_VALUE', { - fieldKey, fieldValue - }); -} diff --git a/app/scripts/actions/navigate.js b/app/scripts/actions/navigate.js deleted file mode 100644 index 6be4f002be..0000000000 --- a/app/scripts/actions/navigate.js +++ /dev/null @@ -1,186 +0,0 @@ -'use strict'; - -var debug = require('debug')('hub:actions:navigate'); -import _ from 'lodash'; -import { - JWT, - Notifications, - Repositories as Repos, - Search, - Users, - Billing -} from 'hub-js-sdk'; -import accountSettings from './navigate/accountSettings'; -import addRepo from './navigate/addRepo'; -import billingPlans from './navigate/billingPlans'; -import bitbucketRedirect from './navigate/bitbucketRedirect'; -import bitbucketUsersAndRepos from './navigate/bitbucketUsersAndRepos'; -import buildsMain from './navigate/buildsMain'; -import buildLogs from './navigate/buildLogs'; -import autoBuildSettings from './navigate/autoBuildSettings'; -import collaborators from './navigate/repoSettingsCollaborators'; -import dashStars from './navigate/dashStars'; -import dashContribs from './navigate/dashContribs'; -import dockerfile from './navigate/dockerfile'; -import explore from './navigate/explore'; -import serverTrial from './navigate/serverTrial'; -import serverTrialSuccess from './navigate/serverTrialSuccess'; -import serverBilling from './navigate/serverBilling'; -import cloudBilling from './navigate/cloudBilling'; -import getNamespaces from './navigate/getNamespaces'; -import githubUsersAndRepos from './navigate/githubUsersAndRepos'; -import githubRedirect from './navigate/githubRedirect'; -import home from './navigate/home'; -import licenses from './navigate/licenses'; -import linkedAccountSettings from './navigate/linkedAccountsSettings'; -import notificationSettings from './navigate/notificationSettings'; -import orgDashBilling from './navigate/orgBilling'; -import orgDashTeams from './navigate/orgDashTeams'; -import orgHome from './navigate/orgHome'; -import orgSummary from './navigate/orgSummary'; -import orgSettings from './navigate/orgSettings'; -import repo from './navigate/repo'; -import repoDetailsTags from './navigate/repoDetailsTags'; -import repoDetailsScannedTag from './navigate/repoDetailsScannedTag'; -import repoOfficial from './navigate/repoOfficial'; -import repoSettings from './navigate/repoSettings'; -import resetPass from './navigate/resetPass'; -import search from './navigate/search'; -import toOrg from './navigate/toOrg.js'; -import UserStore from '../stores/UserStore'; -import user from './navigate/user'; -import userStars from './navigate/userStars'; -import webhooks from './navigate/webhooks'; - -function noop({actionContext, payload, done, maybeData}) { - done(); -} - -function routesHaveHandlerFor(route, routes){ - return _.has(routes, route); -} - -function withUser(actionContext, payload, cb) { - /** - * If we are on the server and payload.cookies.jwt is a - * jwt, use it - */ - if (payload.cookies && payload.cookies.jwt) { - let token = payload.cookies.jwt; - actionContext.dispatch('RECEIVE_JWT', token); - /** - * Use the JWT to get the JWT's user's data. - */ - JWT.getUser(token, function(err, res) { - if (err) { - debug('NOT REALLY EXPIRED. JUST AN ERROR'); - actionContext.dispatch('EXPIRED_SIGNATURE', null); - return cb(null, err); - } else { - var cbData = res.body; - cbData.isAdmin = res.body.is_admin; - actionContext.dispatch('RECEIVE_USER', res.body); - cb(null, {token: token, user: cbData}); - } - }); - } else if (payload.jwt) { - debug('payload has jwt'); - /** - * if we have access to a jwt already, use it instead and assume - * we already have the user data since we're likely on the client - * (and we fill in the user data when a user logs in on the client) - */ - cb(null, { - token: payload.jwt, - user: actionContext.getStore(UserStore).getState() - }); - } else { - debug('no jwt and payload has no cookies; This should not happen'); - /** - * We have no jwt and no error? This shouldn't happen. - */ - cb(null, {}); - } -} - -module.exports = function(actionContext, payload, done) { - var _done = done; - done = function() { - _done.apply(this, arguments); - }; - - if (!payload.location.pathname) { - /** - * if we don't have a pathname, react-router doesn't have a route. - * ignore it. There's nothing we can do. - */ - return done(); - } - - withUser(actionContext, payload, function(err, maybeData) { - if (err) { - debug(err); - return done(); - } - - let routeName = payload.routes[payload.routes.length - 1].name; - debug('routeName', routeName); - let routes = { - 'accountSettings': accountSettings, - 'addRepo': addRepo, - 'addWebhook': noop, - 'addAutoBuild': linkedAccountSettings, // Questionable navigate Route - 'authServicesRoot': linkedAccountSettings, - 'autobuildBitbucket': getNamespaces, - 'autobuildBitbucketOrgs': bitbucketUsersAndRepos, - 'autobuildGithub': getNamespaces, - 'autobuildGithubOrgs': githubUsersAndRepos, - 'autobuildSettings': autoBuildSettings, - 'billingPlans': billingPlans, - 'bitbucketRedirect': bitbucketRedirect, - 'buildLogs': buildLogs, - 'buildsMain': buildsMain, - 'cloudBilling': cloudBilling, - 'collaborators': collaborators, - 'createOrgSubscription': orgDashBilling, - 'createSubscription': billingPlans, - 'dashboardHome': home, - 'dashContribs': dashContribs, - 'dashStars': dashStars, - 'dockerfile': dockerfile, - 'explore': explore, - 'githubRedirect': githubRedirect, - 'licenses': licenses, - 'notifications': notificationSettings, - 'orgDashBilling': orgDashBilling, - 'orgDashHome': orgHome, - 'orgDashSettings': orgSettings, - 'orgDashTeams': orgDashTeams, - 'orgSummary': orgSummary, - 'repoDetailsInfo': repo, - 'repoDetailsTags': repoDetailsTags, - 'repoDetailsScannedTag': repoDetailsScannedTag, - 'repoOfficial': repoOfficial, - 'repoSettingsMain': repoSettings, - 'resetPass': resetPass, - 'search': search, - 'serverBilling': serverBilling, - 'serverTrial': serverTrial, - 'serverTrialSuccess': serverTrialSuccess, - 'toOrg': toOrg, - 'updateBillingInfo': billingPlans, - 'updateOrgBillingInfo': orgDashBilling, - 'user': user, - 'userRepos': user, //This route is a clone of /u/:user/ WHY DO WE HAVE THIS? - 'userStars': userStars, - 'webhooks': webhooks - }; - actionContext.dispatch('CHANGE_ROUTE', payload); - if(routesHaveHandlerFor(routeName, routes)){ - routes[routeName]({ actionContext, payload, done, maybeData }); - } else { - debug(`no handler for ${routeName}`, payload.routes); - done(); - } - }); -}; diff --git a/app/scripts/actions/navigate/accountSettings.js b/app/scripts/actions/navigate/accountSettings.js deleted file mode 100644 index e10642d3b9..0000000000 --- a/app/scripts/actions/navigate/accountSettings.js +++ /dev/null @@ -1,79 +0,0 @@ -'use strict'; -const debug = require('debug')('navigate::accountSettings'); -import { - Emails, - Users -} from 'hub-js-sdk'; -import async from 'async'; -import _ from 'lodash'; - -function sortEmails(emails) { - return _.sortByOrder(emails, - ['primary', 'verified'], - [false, false]); -} - -function parseRes({res, actionContext}) { - let emails = res.body.results; - let sortedEmails = _.sortByOrder(emails, - ['primary', 'verified'], - [false, false]); - return sortedEmails; -} - -export default function accountSettings({ - actionContext, payload, done, maybeData -}){ - actionContext.dispatch('CHANGE_PASS_CLEAR'); - if (_.has(maybeData, 'token')) { - var { token, user } = maybeData; - async.parallel({ - emails: function(callback) { - debug('ACCOUNT SETTINGS EMAILS'); - if (user && user.isAdmin) { - Emails.getEmailsForUser(token, user.username, function(err, res){ - if (err) { - callback(); - } else { - let emails = parseRes({res, actionContext}); - actionContext.dispatch('RECEIVE_EMAILS', {emails: emails}); - callback(null, emails); - } - }); - } else { - Emails.getEmailsJWT(token, function(err, res){ - if (err) { - callback(); - } else { - let emails = parseRes({res, actionContext}); - actionContext.dispatch('RECEIVE_EMAILS', {emails: emails}); - callback(null, emails); - } - }); - } - }, - repoStats: function(callback) { - debug('GET REPO STATS'); - Users.getUserSettings(token, user.username, function(err, res) { - if (err) { - callback(); - } else { - actionContext.dispatch('RECEIVE_PRIVATE_REPOSTATS', res.body); - callback(null, res.body); - } - }); - } - }, function(err, res) { - if (err) { - debug('ERROR', err); - done(); - } else { - let { emails, repoStats } = res; - debug('SUCCESS'); - done(); - } - }); - } else { - done(); - } -} diff --git a/app/scripts/actions/navigate/addRepo.js b/app/scripts/actions/navigate/addRepo.js deleted file mode 100644 index b70b6bb913..0000000000 --- a/app/scripts/actions/navigate/addRepo.js +++ /dev/null @@ -1,66 +0,0 @@ -'use strict'; - -import has from 'lodash/object/has'; -import { - Users -} from 'hub-js-sdk'; -import async from 'async'; -var debug = require('debug')('navigate::ADD REPO'); - -export default function repo({actionContext, payload, done, maybeData}){ - - // Defining functions here so we have access to payload - const getUserSettings = (callback) => { - // Users.getUserSettings === Orgs.getOrgSettings - equivalent calls - let username = maybeData.user.username; - if (payload.location.query.namespace) { - username = payload.location.query.namespace; - } - Users.getUserSettings(maybeData.token, username, function(getErr, getRes) { - // This is to get default visibility. If this fails, we shouldn't block - if (getErr){ - callback(null, getErr); - } else { - callback(null, getRes.body); - } - }); - }; - - const getNamespace = (callback) => { - Users.getNamespacesForUser(maybeData.token, function(namespaceErr, namespaceRes) { - if (namespaceErr) { - // If we don't get back namespaces, we can't do anything, so no point in continuing with the other calls - callback(namespaceErr); - } else { - callback(null, namespaceRes.body); - } - }); - }; - - if (has(maybeData, 'token')) { - async.parallel({ - getNamespace, - getUserSettings - }, - function(err, res) { - actionContext.dispatch('CREATE_REPO_CLEAR_FORM'); - if (err) { - done(); - } else { - const is_private = has(res.getUserSettings, 'default_repo_visibility') ? res.getUserSettings.default_repo_visibility : true; - actionContext.dispatch('CREATE_REPO_UPDATE_FIELD_WITH_VALUE', {fieldKey: 'is_private', fieldValue: is_private}); - actionContext.dispatch('RECEIVE_PRIVATE_REPOSTATS', res.getUserSettings); - if (has(res.getNamespace, 'namespaces')) { - actionContext.dispatch('CREATE_REPO_RECEIVE_NAMESPACES', { - namespaces: res.getNamespace, - selectedNamespace: maybeData.user.username - }); - } - // No namespaces is already handled in AddRepo.jsx - Dispatch is unecessary - done(); - } - }); - } else { - done(); - } -} diff --git a/app/scripts/actions/navigate/autoBuildSettings.js b/app/scripts/actions/navigate/autoBuildSettings.js deleted file mode 100644 index 3d13720ad6..0000000000 --- a/app/scripts/actions/navigate/autoBuildSettings.js +++ /dev/null @@ -1,136 +0,0 @@ -'use strict'; -const debug = require('debug')('navigate::repoBuildSettings'); -import { parallel, waterfall } from 'async'; -import { PENDING_DELETE } from 'common/enums/RepoStatus'; -import _ from 'lodash'; -import { - Repositories as Repos, - Autobuilds as AutoBuild - } from 'hub-js-sdk'; - -function getRepo({maybeToken, actionContext, user, splat}) { - return function(callback){ - Repos.getRepo(maybeToken, `${user}/${splat}`, function(err, res) { - let status; - if (res && res.body) { - status = res.body.status; - } - - if (err || status === PENDING_DELETE) { - debug('GET REPO ERR::', err); - actionContext.dispatch('REPO_NOT_FOUND', err); - return callback(err); - } else { - debug('GETTING REPOSITORY::', res.body); - actionContext.dispatch('RECEIVE_REPOSITORY', res.body); - return callback(null, res.body); - } - }); - }; -} - -function getAutobuildSettings({maybeToken, actionContext, user, splat}) { - return function(callback){ - AutoBuild.getAutomatedBuildSettings(maybeToken, user, splat, function(err, res) { - if (err) { - debug('GET AUTOBUILD SETTINGS ERR::', err); - return callback(null, null); - } - debug('AUTOBUILDSETTINGS', res.body); - actionContext.dispatch('RECEIVE_AUTOBUILD_SETTINGS', res.body); - //also dispatch to the triggerByTag store to initialize the status - const {build_tags} = res.body; - if (build_tags) { - actionContext.dispatch('INITIALIZE_AB_TRIGGERS', build_tags); - } - return callback(null, res.body); - }); - }; -} - -function getAutobuildLinks({maybeToken, actionContext, user, splat}) { - return function(callback) { - AutoBuild.getAutomatedBuildLinks(maybeToken, user, splat, function(err, res) { - if (err) { - debug('GET AUTOBUILD LINKS ERR::', err); - return callback(null, null); - } - debug('AUTOBUILDLINKS', res.body); - actionContext.dispatch('RECEIVE_AUTOBUILD_LINKS', res.body.results); - return callback(null, res.body); - }); - }; -} - -function getTriggerStatus({maybeToken, actionContext, user, splat}) { - return function(callback) { - AutoBuild.getTriggerStatus(maybeToken, user, splat, function(err, res) { - if (err) { - debug('GET TRIGGER STATUS ERR::', err); - const defaultStatus = { - token: '', - trigger_url: '', - active: false - }; - actionContext.dispatch('RECEIVE_TRIGGER_STATUS', defaultStatus); - return callback(null, null); - } - debug('AUTOBUILDTRIGGERS', res.body); - actionContext.dispatch('RECEIVE_TRIGGER_STATUS', res.body); - return callback(null, res.body); - }); - }; -} - -function getTriggerLogs({maybeToken, actionContext, user, splat}) { - return function(callback) { - AutoBuild.getTriggerLogs(maybeToken, user, splat, function(err, res) { - if (err) { - debug('GET TRIGGER LOGS ERROR', err.res); - return callback(null, null); - } - debug('AUTOBUILDTRIGGERLOGS', res.body); - actionContext.dispatch('RECEIVE_TRIGGER_LOGS', res.body.results); - return callback(null, res.body.results); - }); - }; -} - -function getRest(args) { - return function(repoDetails, cbk) { - if (repoDetails) { - parallel({ - getAutoBuild: getAutobuildSettings(args), - getAutoLinks: getAutobuildLinks(args), - getTriggerStatus: getTriggerStatus(args), - getTriggerLogs: getTriggerLogs(args) - }, function (err, res) { - cbk(null, res); - }); - } else { - cbk(null); - } - }; -} - -export default function repoSettingsBuilds({actionContext, payload, done, maybeData}) { - debug('maybeData:', maybeData); - if (_.has(maybeData, 'token')) { - let args = { - actionContext, - maybeToken: maybeData.token, - user: payload.params.user, - splat: payload.params.splat - }; - - waterfall([ - getRepo(args), - getRest(args) - ], function (e, r) { - done(); - }); - } else { - actionContext.dispatch('REPO_NOT_FOUND', null); - done(); - } -} diff --git a/app/scripts/actions/navigate/billingPlans.js b/app/scripts/actions/navigate/billingPlans.js deleted file mode 100644 index 857edd4778..0000000000 --- a/app/scripts/actions/navigate/billingPlans.js +++ /dev/null @@ -1,145 +0,0 @@ -'use strict'; - -const debug = require('debug')('navigate::billingPlans'); -import async from 'async'; -import _ from 'lodash'; -import { - BILLFORWARD_ACCOUNT_ID -} from 'stores/common/Constants.js'; - -import { - Billing -} from 'hub-js-sdk'; - -function _getPersonalPlans({token}) { - return (callback) => { - Billing.getPlans(token, 'personal', (err, res) => { - if(err) { - debug(err); - callback(null, []); - } else { - let plansList = res.body; - let sortedPlans = _.sortBy(plansList, 'display_order'); - callback(null, sortedPlans); - } - }); - }; -} - -function _getBillingSubscriptions({token, user}) { - return (callback) => { - Billing.getBillingSubscriptions(token, user.username, (err, res) => { - if(!res || res.status === 500) { - debug('SERVER ISSUE: getting subscriptions'); - callback('SERVER ISSUE'); - } else if (err) { - callback(null, res.body); - } else { - debug('GET USER PLANS', res.body); - let subscriptions = res.body; - - // the assumption is that there is at most one subscription right now - let subscription = _.head(subscriptions); - callback(err, subscription); - } - }); - }; -} - -function _getBillingAccount({token, user}) { - return (callback) => { - Billing.getBillingAccount(token, user.username, (err, res) => { - if(!res || res.status === 500) { - debug('SERVER ISSUE: getting billing account info'); - // NOTE: If this is a brand new billing account - set newBilling to true - callback(null, {account: { newBilling: true }}); - } else if (err) { - debug('NO BILLING ACCOUNT CONNECTED'); - // NOTE: If this is a brand new billing account - set newBilling to true - callback(null, {account: { newBilling: true }}); - } else { - debug('GET BILLING ACCOUNT', res.body); - const account = { ...res.body, newBilling: false }; - callback(err, { account, billforwardId: res.header[BILLFORWARD_ACCOUNT_ID] }); - } - }); - }; -} - -function _getBillingInfo({token, user}) { - return (callback) => { - Billing.getBillingInfo(token, user.username, (err, res) => { - if(!res || res.status === 500) { - debug('SERVER ISSUE: getting billing info'); - // NOTE: If this is a brand new billing profile - set newBilling to true - callback(null, { newBilling: true }); - } else if (err) { - debug('NO BILLING INFO CONNECTED'); - // NOTE: If this is a brand new billing profile - set newBilling to true - callback(null, { newBilling: true }); - } else { - debug('GET BILLING INFO', res.body); - callback(err, { ...res.body, newBilling: false }); - } - }); - }; -} - -function _getBillingInvoices({token, user}) { - return (callback) => { - Billing.getBillingInvoices(token, user.username, (err, res) => { - if(err) { - debug('NO BILLING ACCOUNT CONNECTED'); - callback(null, []); - } else { - debug('GET BILLING INVOICES', res.body); - callback(err, res.body); - } - }); - }; -} - -export default function billingPlans({actionContext, payload, done, maybeData}){ - if (maybeData.token && maybeData.user) { - let {token, user} = maybeData; - actionContext.dispatch('RESET_BILLING_PLANS'); - /* - NOTE: - None of the functions should pass an error into the callback or else it will - kill the rest of the calls and return before we're able to fetch all the data - */ - async.parallel({ - allPlans: _getPersonalPlans({token}), - userPlan: _getBillingSubscriptions({token, user}), - accountInfo: _getBillingAccount({token, user}), - billingInfo: _getBillingInfo({token, user}), - invoiceList: _getBillingInvoices({token, user}) - }, function(err, results){ - const { - allPlans, - userPlan, - accountInfo, - billingInfo, - invoiceList - } = results; - debug('BILLING PLANS', results); - // IF AN ACCOUNT HAS BEEN MIGRATED - ITS ACCOUNT INFO WILL HAVE PARAMETER 'payment_gateway' === 'stripe' - const gateway = accountInfo && accountInfo.account && accountInfo.account.payment_gateway; - const billforwardId = accountInfo && accountInfo.billforwardId; - actionContext.dispatch('RECEIVE_BILLING_PLANS', { - plansList: allPlans - }); - actionContext.dispatch('RECEIVE_BILLING_INFO', { - billingInfo: billingInfo, - accountInfo: accountInfo && accountInfo.account, - currentPlan: userPlan, - gateway, - billforwardId - }); - actionContext.dispatch('RECEIVE_INVOICES', {invoices: invoiceList}); - return done(); - }); - } else { - done(); - } -} diff --git a/app/scripts/actions/navigate/bitbucketRedirect.js b/app/scripts/actions/navigate/bitbucketRedirect.js deleted file mode 100644 index d8e698dda3..0000000000 --- a/app/scripts/actions/navigate/bitbucketRedirect.js +++ /dev/null @@ -1,75 +0,0 @@ -'use strict'; - -import async from 'async'; -import has from 'lodash/object/has'; -import { Builds } from 'hub-js-sdk'; -import linkedAccountSettingsAction from './linkedAccountsSettings'; -var debug = require('debug')('navigate::bitbucketRedirect'); - -/** - * This action is hit when the site gets redirected from the github oauth workflow - * @param actionContext - * @param payload - * @param done - * @param maybeData - */ -export default function bitbucketRedirect({actionContext, payload, done, maybeData}){ - - const SOURCES = { - GITHUB: 'github', - BITBUCKET: 'bitbucket' - }; - - debug('In Bitbucket Redirect Route Handler !'); - //If token is available the user is already logged in - var token; - if (has(maybeData, 'token')) { - token = maybeData.token; - var oauthVerifier = payload.location.query.oauth_verifier; - var oauthToken = payload.location.query.oauth_token; - - var _associateBitbucketAccount = function(cb) { - Builds.associateBitbucketAccount(token, {oauth_verifier: oauthVerifier, oauth_token: oauthToken}, function(err, res) { - if (err) { - debug(JSON.stringify(err)); - debug('ERROR ASSOCIATING BITBUCKET ACCOUNT: ' + err); - const { detail } = err.response.body; - if(detail) { - actionContext.dispatch('BITBUCKET_ASSOCIATE_ERROR', detail); - } - cb(err); - } else { - if (res.body) { - debug('Bitbucket account association Success: ' + res.body); - actionContext.dispatch('BITBUCKET_ASSOCIATE_SUCCESS', res.body); - cb(null, res.body); - } - } - }); - }; - - var _getLinkedAccounts = function(callback) { - debug('Getting linked account settings state.'); - linkedAccountSettingsAction( - { - actionContext: actionContext, - payload: payload, - done: callback, - maybeData: maybeData - } - ); - }; - - async.series([ - _associateBitbucketAccount, - _getLinkedAccounts - ], function(err, results) { - done(); - } - ); - } else { - token = ''; - //TODO: redirect to login page or test redirect happens automatically - done(); - } -} diff --git a/app/scripts/actions/navigate/bitbucketUsersAndRepos.js b/app/scripts/actions/navigate/bitbucketUsersAndRepos.js deleted file mode 100644 index 365a8f28d6..0000000000 --- a/app/scripts/actions/navigate/bitbucketUsersAndRepos.js +++ /dev/null @@ -1,49 +0,0 @@ -'use strict'; - -var debug = require('debug')('navigate::bitbucketRepos'); -import async from 'async'; -import { - Builds - } from 'hub-js-sdk'; -import has from 'lodash/object/has'; -import linkedAccountAction from './linkedAccountsSettings'; -var debug = require('debug')('navigate::bitbucketUsersAndRepos'); - -export default function getBitbucketRepos({actionContext, payload, done, maybeData}) { - debug('GET BITBUCKET REPOS'); - var _getLinkedAccountStatus = function(cb) { - linkedAccountAction({ - actionContext: actionContext, - payload: payload, - done: cb, - maybeData: maybeData}); - }; - - var _getSourceRepos = function(cb) { - Builds.getSourceRepos('bitbucket', maybeData.token, function (err, res) { - if (err) { - const { detail } = err.response.body; - if (detail) { - actionContext.dispatch('LINKED_REPO_SOURCES_ERROR', detail); - } - cb(null); - } else{ - cb(null, res.body); - } - }); - }; - - - if (has(maybeData, 'token')) { - async.parallel([ - _getLinkedAccountStatus, - _getSourceRepos - ], function(err, results) { - actionContext.dispatch('SET_LINKED_REPO_TYPE', 'bitbucket'); - actionContext.dispatch('RECEIVE_LINKED_REPO_SOURCES', results[1]); - done(); - }); - } else { - done(); - } -} diff --git a/app/scripts/actions/navigate/buildLogs.js b/app/scripts/actions/navigate/buildLogs.js deleted file mode 100644 index 21f0240a8e..0000000000 --- a/app/scripts/actions/navigate/buildLogs.js +++ /dev/null @@ -1,105 +0,0 @@ -'use strict'; - -import has from 'lodash/object/has'; -import { parallel, waterfall } from 'async'; -import request from 'superagent'; -import { PENDING_DELETE } from 'common/enums/RepoStatus'; -import { - Repositories as Repos, - Autobuilds -} from 'hub-js-sdk'; -const debug = require('debug')('buildLogs'); - -export default function buildLogs({actionContext, payload, done, maybeData}) { - var token; - if (has(maybeData, 'token')) { - token = maybeData.token; - } else { - token = ''; - } - - var namespace = payload.params.user; - if (payload.params.user === '_') { - namespace = 'library'; - } - var repoShortName = namespace + '/' + payload.params.splat; - const build_code = payload.params.build_code; - - var _getRepo = function (callback) { - Repos.getRepo(token, repoShortName, function (err, res) { - let status; - if (res && res.body) { - status = res.body.status; - } - - if (err || status === PENDING_DELETE) { - actionContext.dispatch('REPO_NOT_FOUND', err); - callback(err); - } else { - actionContext.dispatch('RECEIVE_REPOSITORY', res.body); - callback(null, res.body); - } - }); - }; - - var _getRest = function (repoDetail, cb) { - if (repoDetail) { - parallel([ - function (callback) { - Repos.getCommentsForRepo(token, repoShortName, function (err, res) { - if (err) { - callback(err); - } else { - callback(null, res.body); - } - }); - }, function (callback) { - request.get(process.env.REGISTRY_API_BASE_URL + '/v2/repositories/' + repoShortName + '/buildhistory/' + build_code + '/') - .accept('application/json') - .set('Authorization', 'JWT ' + token) - .end((err, res) => { - if(err) { - callback(); - } else { - debug('BUILD LOGS RECEIVE', res.body); - actionContext.dispatch('BUILD_LOGS_RECEIVE', res.body); - callback(); - } - }); - }, function (callback) { - if (repoDetail.is_automated) { - Autobuilds.getAutomatedBuildSettings(token, namespace, payload.params.splat, function (err, res) { - if (err) { - actionContext.dispatch('AUTOBUILD_REPO_NOT_FOUND'); - callback(err); - } else { - actionContext.dispatch('RECEIVE_AUTOBUILD_SETTINGS', res.body); - callback(); - } - }); - } else { - callback(); - } - } - ], - function (error, results) { - if (error) { - cb(); - } else { - actionContext.dispatch('RECEIVE_REPO_COMMENTS', results[0]); - cb(); - } - }); - } else { - cb(); - } - }; - - waterfall([ - _getRepo, - _getRest - ], function(err, res) { - done(); - }); - -} diff --git a/app/scripts/actions/navigate/buildsMain.js b/app/scripts/actions/navigate/buildsMain.js deleted file mode 100644 index 5e2bc2b681..0000000000 --- a/app/scripts/actions/navigate/buildsMain.js +++ /dev/null @@ -1,99 +0,0 @@ -'use strict'; - -import has from 'lodash/object/has'; -import { parallel, waterfall } from 'async'; -import { PENDING_DELETE } from 'common/enums/RepoStatus'; -import { - Repositories as Repos, - Autobuilds -} from 'hub-js-sdk'; - -export default function buildsMain({actionContext, payload, done, maybeData}) { - var token; - if (has(maybeData, 'token')) { - token = maybeData.token; - } else { - token = ''; - } - - var namespace = payload.params.user; - if (payload.params.user === '_') { - namespace = 'library'; - } - var repoShortName = namespace + '/' + payload.params.splat; - - var _getRepo = function (callback) { - Repos.getRepo(token, repoShortName, function (err, res) { - let status; - if (res && res.body) { - status = res.body.status; - } - - if (err || status === PENDING_DELETE) { - actionContext.dispatch('REPO_NOT_FOUND', err); - callback(err); - } else { - actionContext.dispatch('RECEIVE_REPOSITORY', res.body); - callback(null, res.body); - } - }); - }; - - var _getRest = function (repoDetail, cb) { - if (repoDetail) { - parallel([ - function (callback) { - Repos.getBuildHistory(token, { - namespace, - name: payload.params.splat - }, function (err, res) { - if (err) { - callback(); - } else { - actionContext.dispatch('RECEIVE_BUILD_HISTORY_FOR_REPOSITORY', res.body); - callback(); - } - }); - }, function(callback) { - if (repoDetail.is_automated) { - Autobuilds.getAutomatedBuildSettings(token, namespace, payload.params.splat, function (err, res) { - if (err) { - actionContext.dispatch('AUTOBUILD_REPO_NOT_FOUND'); - callback(null); - } else { - callback(null, res.body); - } - }); - } else { - callback(null); - } - } - ], - function (error, results) { - if (error) { - cb(); - } else { - if (results[1]) { - actionContext.dispatch('RECEIVE_AUTOBUILD_SETTINGS', results[1]); - //also dispatch to the triggerByTag store to initialize the status - const {build_tags} = results[1]; - if (build_tags) { - actionContext.dispatch('INITIALIZE_AB_TRIGGERS', build_tags); - } - } - cb(); - } - }); - } else { - cb(); - } - }; - - waterfall([ - _getRepo, - _getRest - ], function(err, res) { - done(); - }); - -} diff --git a/app/scripts/actions/navigate/cloudBilling.js b/app/scripts/actions/navigate/cloudBilling.js deleted file mode 100644 index 4fbb8e1368..0000000000 --- a/app/scripts/actions/navigate/cloudBilling.js +++ /dev/null @@ -1,109 +0,0 @@ -'use strict'; - -const debug = require('debug')('navigate::billingPlans'); -import async from 'async'; -import _ from 'lodash'; - -import { - Billing, - Users - } from 'hub-js-sdk'; - -//GETs current HUB subscription -function _getBillingSubscriptions({token, user}) { - return (callback) => { - Billing.getBillingSubscriptions(token, user.username, (err, res) => { - if(err) { - callback(null, {}); - } else { - debug('GET USER PLANS', res.body); - let subscriptions = res.body; - - // the assumption is that there is at most one subscription right now - let subscription = _.head(subscriptions); - callback(err, subscription); - } - }); - }; -} - -function _getBillingAccount({token, user}) { - return (callback) => { - Billing.getBillingAccount(token, user.username, (err, res) => { - if(err) { - debug('NO BILLING ACCOUNT CONNECTED'); - callback(null, {}); - } else { - debug('GET BILLING ACCOUNT', res.body); - callback(null, res.body); - } - }); - }; -} - -function _getBillingInfo({token, user}) { - return (callback) => { - Billing.getBillingInfo(token, user.username, (err, res) => { - if(err) { - debug('NO BILLING ACCOUNT CONNECTED'); - callback(null, {}); - } else { - debug('GET BILLING INFO', res.body); - callback(null, res.body); - } - }); - }; -} -/** - * ============================================= - * ^ GET SUBSCRIPTIONS/ACCOUNTINFO/BILLINGINFO - * Must re-get on change of namespace - * ============================================= - */ - -//GET namespaces for user -function _getNamespaces({token}) { - return (callback) => { - Users.getNamespacesForUser(token, function(err, res) { - if (err) { - callback(null, {}); - } else { - callback(null, res.body.namespaces); - } - }); - }; -} - -export default function billingPlans({actionContext, payload, done, maybeData}){ - if (maybeData.token && maybeData.user) { - const {token, user} = maybeData; - actionContext.dispatch('RESET_CLOUD_BILLING_PLANS'); - async.parallel({ - userPlan: _getBillingSubscriptions({token, user}), - accountInfo: _getBillingAccount({token, user}), - billingInfo: _getBillingInfo({token, user}), - namespaces: _getNamespaces({token}) - }, function(err, results){ - const { userPlan, accountInfo, billingInfo, namespaces } = results; - debug('CLOUD BILLING PLANS', results); - actionContext.dispatch('RECEIVE_CLOUD_BILLING_INFO', { - billingInfo: billingInfo, - accountInfo: accountInfo, - currentPlan: userPlan - }); - actionContext.dispatch('ENTERPRISE_PAID_RECEIVE_ORGS', namespaces); - const values = _.merge({}, billingInfo, { - account_first: accountInfo.first_name, - account_last: accountInfo.last_name, - company_name: accountInfo.company_name, - email: accountInfo.email - }); - debug('INITIALIZE ENTERPRISE BILLING FORM: ', values); - // Need to differentiate btw billingInfo/accountInfo first/last names - actionContext.dispatch('ENTERPRISE_PAID_POPULATE_FORM', values); - return done(); - }); - } else { - done(); - } -} diff --git a/app/scripts/actions/navigate/dashContribs.js b/app/scripts/actions/navigate/dashContribs.js deleted file mode 100644 index 45f607930e..0000000000 --- a/app/scripts/actions/navigate/dashContribs.js +++ /dev/null @@ -1,78 +0,0 @@ -'use strict'; -var debug = require('debug')('navigate::dashStars'); -import async from 'async'; -import _ from 'lodash'; -import { - Repositories as Repos, - Notifications, - Orgs, - Users - } from 'hub-js-sdk'; - -export default function home({actionContext, payload, done, maybeData}){ - if (_.has(maybeData, 'token')) { - - //This is always for current user - //Get contributed repos - var _getReposByFilterTypeContrib = function(cb) { - var username = maybeData.user.username; - Repos.getContributedReposForUser(maybeData.token, username, function (err, res) { - if (err) { - cb(); - } else { - actionContext.dispatch('RECEIVE_CONTRIB', res.body); - cb(); - } - }, payload.location.query.page); - }; - - - //Get orgs for user - var _getOrgsForCurrentUser = function(cb) { - Users.getOrgsForUser(maybeData.token, function(err, res) { - if (err) { - debug(err); - cb(); - } else { - actionContext.dispatch('RECEIVE_DASHBOARD_NAMESPACES', { - orgs: res.body, - user: maybeData.user.username - }); - cb(); - } - }); - }; - - //Get user settings for private repo stats - var _getUserSettings = function(cb) { - Users.getUserSettings(maybeData.token, maybeData.user.username, function(err, res) { - if (err) { - debug(err); - cb(); - } else { - actionContext.dispatch('RECEIVE_PRIVATE_REPOSTATS', res.body); - cb(); - } - }); - }; - - //This is executed only for the currently logged in user, so put in starred, contributed only here - var _doParallelCalls = function() { - async.parallel([ - _getOrgsForCurrentUser, - _getReposByFilterTypeContrib, - _getUserSettings - ], function(err, results) { - if (err) { - debug(err); - } - return done(); - }); - }; - - actionContext.dispatch('CURRENT_USER_CONTEXT', { username: maybeData.user.username }); - _doParallelCalls(); - } else { - done(); - } -} diff --git a/app/scripts/actions/navigate/dashRepos.js b/app/scripts/actions/navigate/dashRepos.js deleted file mode 100644 index 3aeffbdf48..0000000000 --- a/app/scripts/actions/navigate/dashRepos.js +++ /dev/null @@ -1,138 +0,0 @@ -'use strict'; -var debug = require('debug')('navigate::dashRepos'); -import async from 'async'; -import _ from 'lodash'; -import { - Repositories as Repos, - Notifications, - Orgs, - Users -} from 'hub-js-sdk'; - -export default function home({actionContext, payload, done, maybeData}){ - if (_.has(maybeData, 'token')) { - - //Get repos for user or org - var _getReposForUserOrOrg = function(cb, userType) { - var userOrOrgName = payload.params.user || maybeData.user.username; - actionContext.dispatch('DASHBOARD_REPOS_STORE_ATTEMPTING_GET_REPOS'); - Repos.getReposForUser(maybeData.token, userOrOrgName, function(err, res) { - if (err) { - actionContext.dispatch('ERROR_RECEIVING_REPOS'); - cb(); - } else { - actionContext.dispatch('RECEIVE_REPOS', res.body); - cb(); - } - }, payload.location.query.page); - }; - - //Get orgs for user - var _getOrgsForCurrentUser = function(cb) { - Users.getOrgsForUser(maybeData.token, function(err, res) { - if (err) { - debug(err); - cb(); - } else { - actionContext.dispatch('CURRENT_USER_ORGS', res.body); - cb(); - } - }); - }; - - //Get user settings for private repo stats - var _getUserSettings = function(cb) { - Users.getUserSettings(maybeData.token, maybeData.user.username, function(err, res) { - if (err) { - debug(err); - cb(); - } else { - actionContext.dispatch('RECEIVE_PRIVATE_REPOSTATS', res.body); - cb(); - } - }); - }; - - //This is executed only for the currently logged in user, so put in starred, contributed only here - var _doParallelCalls = function() { - async.parallel([ - _getReposForUserOrOrg, - _getOrgsForCurrentUser, - _getUserSettings, - function(callback) { - Notifications.getActivityFeed(maybeData.token, function(err, res) { - if (res) { - actionContext.dispatch('RECEIVE_ACTIVITY_FEED', res.body); - } - callback(); - }); - } - ], function(err, results) { - if (err) { - debug(err); - } - return done(); - }); - }; - - //Get Organization by name - var _getOrgByName = function() { - Orgs.getOrg(maybeData.token, payload.params.user, function(err, res) { - if (err) { - debug(err); - } else { - var org = res.body; - if (!_.isEmpty(org)) { - return org; - } - } - }); - return {}; - }; - - //Get user by name - var _getUserByName = function() { - Users.getUser(maybeData.token, payload.params.user, function(err, res) { - if (err) { - debug(err); - } else { - var user = res.body; - if (!_.isEmpty(user)) { - return user; - } - } - }); - return {}; - }; - - if (payload.params.user) { - if (payload.params.user === maybeData.user.username) { - actionContext.dispatch('CURRENT_USER_CONTEXT', { username: payload.params.user }); - _doParallelCalls(); - } else { - //get Org by name, if success set userOrOrg = `org` else set it to `user` - async.series([ - function (callback) { - callback(null, _getOrgByName(payload.params.user)); - }, - function (callback) { - callback(null, _getUserByName(payload.params.user)); - } - ], function (err, results) { - if (err) { - debug(err); - } else { - debug('Results of Series Call: ' + JSON.stringify(results)); - actionContext.dispatch('CURRENT_USER_CONTEXT', { username: payload.params.user }); - _getReposForUserOrOrg(done); - } - }); - } - } else { - actionContext.dispatch('CURRENT_USER_CONTEXT', { username: maybeData.user.username }); - _doParallelCalls(); - } - } else { - done(); - } -} diff --git a/app/scripts/actions/navigate/dashStars.js b/app/scripts/actions/navigate/dashStars.js deleted file mode 100644 index 5744f62161..0000000000 --- a/app/scripts/actions/navigate/dashStars.js +++ /dev/null @@ -1,77 +0,0 @@ -'use strict'; -var debug = require('debug')('navigate::dashStars'); -import async from 'async'; -import _ from 'lodash'; -import { - Repositories as Repos, - Notifications, - Orgs, - Users -} from 'hub-js-sdk'; - -export default function home({actionContext, payload, done, maybeData}){ - if (_.has(maybeData, 'token')) { - - //This is always for current user - //Get starred repos - var _getReposByFilterTypeStarred = function(cb) { - var username = maybeData.user.username; - Repos.getStarredReposForUser(maybeData.token, username, function (err, res) { - if (err) { - cb(); - } else { - actionContext.dispatch('RECEIVE_STARRED', res.body); - cb(); - } - }, payload.location.query.page); - }; - - //Get orgs for user - var _getOrgsForCurrentUser = function(cb) { - Users.getOrgsForUser(maybeData.token, function(err, res) { - if (err) { - debug(err); - cb(); - } else { - actionContext.dispatch('RECEIVE_DASHBOARD_NAMESPACES', { - orgs: res.body, - user: maybeData.user.username - }); - cb(); - } - }); - }; - - //Get user settings for private repo stats - var _getUserSettings = function(cb) { - Users.getUserSettings(maybeData.token, maybeData.user.username, function(err, res) { - if (err) { - debug(err); - cb(); - } else { - actionContext.dispatch('RECEIVE_PRIVATE_REPOSTATS', res.body); - cb(); - } - }); - }; - - //This is executed only for the currently logged in user, so put in starred, contributed only here - var _doParallelCalls = function() { - async.parallel([ - _getOrgsForCurrentUser, - _getReposByFilterTypeStarred, - _getUserSettings - ], function(err, results) { - if (err) { - debug(err); - } - return done(); - }); - }; - - actionContext.dispatch('CURRENT_USER_CONTEXT', { username: maybeData.user.username }); - _doParallelCalls(); - } else { - done(); - } -} diff --git a/app/scripts/actions/navigate/dockerfile.js b/app/scripts/actions/navigate/dockerfile.js deleted file mode 100644 index d43d6afda5..0000000000 --- a/app/scripts/actions/navigate/dockerfile.js +++ /dev/null @@ -1,90 +0,0 @@ -'use strict'; - -import has from 'lodash/object/has'; -import { parallel, waterfall } from 'async'; -import { PENDING_DELETE } from 'common/enums/RepoStatus'; -import { - Repositories as Repos, - Autobuilds -} from 'hub-js-sdk'; - -export default function dockerfile({actionContext, payload, done, maybeData}){ - var token; - if (has(maybeData, 'token')) { - token = maybeData.token; - } else { - token = ''; - } - - var namespace = payload.params.user; - if(payload.params.user === '_') { - namespace = 'library'; - } - var repoShortName = namespace + '/' + payload.params.splat; - - var _getRepo = function (callback) { - Repos.getRepo(token, repoShortName, function (err, res) { - let status; - if (res && res.body) { - status = res.body.status; - } - - if (err || status === PENDING_DELETE) { - actionContext.dispatch('REPO_NOT_FOUND', err); - callback(err); - } else { - actionContext.dispatch('RECEIVE_REPOSITORY', res.body); - callback(null, res.body); - } - }); - }; - - var _getRest = function (repoDetail, cb) { - if (repoDetail) { - parallel([ - function (callback) { - Repos.getDockerfile(token, repoShortName, function (err, res) { - if (err) { - callback(); - } else { - actionContext.dispatch('RECEIVE_DOCKERFILE_FOR_REPOSITORY', res.body); - callback(); - } - }); - }, function(callback) { - if (repoDetail.is_automated) { - Autobuilds.getAutomatedBuildSettings(token, namespace, payload.params.splat, function (err, res) { - if (err) { - actionContext.dispatch('AUTOBUILD_REPO_NOT_FOUND'); - callback(null); - } else { - callback(null, res.body); - } - }); - } else { - callback(null); - } - } - ], - function (error, results) { - if (error) { - cb(); - } else { - if (results[1]) { - actionContext.dispatch('RECEIVE_AUTOBUILD_SETTINGS', results[1]); - } - cb(); - } - }); - } else { - cb(); - } - }; - - waterfall([ - _getRepo, - _getRest - ], function(err, res) { - done(); - }); -} diff --git a/app/scripts/actions/navigate/explore.js b/app/scripts/actions/navigate/explore.js deleted file mode 100644 index 1167f1ef23..0000000000 --- a/app/scripts/actions/navigate/explore.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; -var debug = require('debug')('navigate::home'); -import async from 'async'; -import _ from 'lodash'; -import { - Repositories as Repos, - Notifications, - Orgs, - Users -} from 'hub-js-sdk'; - -export default function explore({actionContext, payload, done, maybeData}){ - - //Get repos for library - // We have, hijacked the repos store. This might not be good - // in the long run - Repos.getReposForUser(maybeData.token, 'library', function(err, res) { - if (err) { - actionContext.dispatch('ERROR_RECEIVING_REPOS'); - done(); - } else { - actionContext.dispatch('RECEIVE_REPOS', res.body); - done(); - } - }, payload.location.query.page); -} diff --git a/app/scripts/actions/navigate/getNamespaces.js b/app/scripts/actions/navigate/getNamespaces.js deleted file mode 100644 index 99376c1547..0000000000 --- a/app/scripts/actions/navigate/getNamespaces.js +++ /dev/null @@ -1,38 +0,0 @@ -'use strict'; - -import _ from 'lodash'; -import { - Users - } from 'hub-js-sdk'; -var debug = require('debug')('navigate::getNamespaces'); - -export default function getNamespaces({actionContext, payload, done, maybeData}){ - var initialRepoName = payload.params.sourceRepoName; - var initialNamespace = payload.location.query.namespace || maybeData.user.username; - if (_.has(maybeData, 'token')) { - Users.getNamespacesForUser(maybeData.token, function(err, res) { - if (err) { - return done(); - } - Users.getUserSettings(maybeData.token, maybeData.user.username, function(settingsErr, settingsRes) { - if (settingsRes.body) { - actionContext.dispatch('RECEIVE_PRIVATE_REPOSTATS', settingsRes.body); - actionContext.dispatch('RECEIVE_NAMESPACES', res.body); - actionContext.dispatch('INITIALIZE_AUTOBUILD_FORM', {name: initialRepoName, namespace: initialNamespace}); - actionContext.dispatch('CLEAR_AUTOBUILD_FORM_ERRORS'); - if (payload.routes[payload.routes.length - 1].name === 'autobuildGithub') { - actionContext.dispatch('SET_LINKED_REPO_TYPE', 'github'); - } else if (payload.routes[payload.routes.length - 1].name === 'autobuildBitbucket') { - actionContext.dispatch('SET_LINKED_REPO_TYPE', 'bitbucket'); - } - return done(); - } else if (settingsErr) { - debug(settingsErr); - return done(); - } - }); - }); - } else { - done(); - } -} diff --git a/app/scripts/actions/navigate/githubRedirect.js b/app/scripts/actions/navigate/githubRedirect.js deleted file mode 100644 index ab96875e57..0000000000 --- a/app/scripts/actions/navigate/githubRedirect.js +++ /dev/null @@ -1,84 +0,0 @@ -'use strict'; - -import _ from 'lodash'; -import async from 'async'; -import { Builds } from 'hub-js-sdk'; -import request from 'superagent'; -var debug = require('debug')('navigate::githubRedirect'); -import GithubLinkStore from '../../stores/GithubLinkStore'; -import linkedAccountSettingsAction from './linkedAccountsSettings'; - -/** - * This action is hit when the site gets redirected from the github oauth workflow - * @param actionContext - * @param payload - * @param done - * @param maybeData - */ -export default function githubRedirect({actionContext, payload, done, maybeData}){ - - const SOURCES = { - GITHUB: 'github', - BITBUCKET: 'bitbucket' - }; - - debug('In Gihub Redirect Route Handler !'); - //If token is available the user is already logged in - var token; - if (_.has(maybeData, 'token')) { - token = maybeData.token; - var code = payload.location.query.code; - var state = payload.location.query.state; - - var _associateGithubAccount = function(cb) { - Builds.associateGithubAccount(token, code, function(err, res) { - if (err) { - debug(JSON.stringify(err)); - debug('ERROR ASSOCIATING GITHUB ACCOUNT: ' + err); - actionContext.dispatch('GITHUB_ASSOCIATE_ERROR', err); - cb(err); - } else { - if (res.body) { - debug('GitHub account association Success: ' + res.body); - actionContext.dispatch('GITHUB_ASSOCIATE_SUCCESS', res.body); - cb(null, res.body); - } - } - }); - }; - - var _getLinkedAccounts = function(callback) { - debug('Getting linked account settings state.'); - linkedAccountSettingsAction( - { - actionContext: actionContext, - payload: payload, - done: callback, - maybeData: maybeData - } - ); - }; - - debug('Payload Cookies: ' + payload.cookies); - //TODO: validate state before linking - if (payload.cookies && payload.cookies.ghOauthKey === state) { - async.series([ - _associateGithubAccount, - _getLinkedAccounts - ], function(err, results) { - request.post('/oauth/github-done/') - .end(function(e, r) { debug('github-oauth done or exited.'); }); - done(); - } - ); - } else { - //The validation of the state failed - actionContext.dispatch('GITHUB_SECURITY_ERROR', 'There was a security issue with your request. Please try again later.'); - done(); - } - } else { - token = ''; - actionContext.dispatch('GITHUB_ASSOCIATE_ERROR'); - done(); - } -} diff --git a/app/scripts/actions/navigate/githubUsersAndRepos.js b/app/scripts/actions/navigate/githubUsersAndRepos.js deleted file mode 100644 index da5bb49ded..0000000000 --- a/app/scripts/actions/navigate/githubUsersAndRepos.js +++ /dev/null @@ -1,48 +0,0 @@ -'use strict'; - -var debug = require('debug')('navigate::githubRepos'); -import async from 'async'; -import { - Builds - } from 'hub-js-sdk'; -import has from 'lodash/object/has'; -import linkedAccountAction from './linkedAccountsSettings'; - -export default function getGithubRepos({actionContext, payload, done, maybeData}) { - - var _getLinkedAccountStatus = function(cb) { - linkedAccountAction({ - actionContext: actionContext, - payload: payload, - done: cb, - maybeData: maybeData}); - }; - - var _getSourceRepos = function(cb) { - Builds.getSourceRepos('github', maybeData.token, function (err, res) { - if (err) { - const { detail } = err.response.body; - if (detail) { - actionContext.dispatch('LINKED_REPO_SOURCES_ERROR', detail); - } - cb(null); - } else{ - cb(null, res.body); - } - }); - }; - - - if (has(maybeData, 'token')) { - async.parallel([ - _getLinkedAccountStatus, - _getSourceRepos - ], function(err, results) { - actionContext.dispatch('SET_LINKED_REPO_TYPE', 'github'); - actionContext.dispatch('RECEIVE_LINKED_REPO_SOURCES', results[1]); - done(); - }); - } else { - done(); - } -} diff --git a/app/scripts/actions/navigate/home.js b/app/scripts/actions/navigate/home.js deleted file mode 100644 index 144c26efe9..0000000000 --- a/app/scripts/actions/navigate/home.js +++ /dev/null @@ -1,132 +0,0 @@ -'use strict'; -var debug = require('debug')('navigate::home'); -import async from 'async'; -import _ from 'lodash'; -import { - Repositories as Repos, - Notifications, - Orgs, - Users -} from 'hub-js-sdk'; - -export default function home({actionContext, payload, done, maybeData}){ - if (_.has(maybeData, 'token')) { - - //Get repos for user or org - var _getReposForUserOrOrg = function(cb, userType) { - var userOrOrgName = payload.params.user || maybeData.user.username; - actionContext.dispatch('DASHBOARD_REPOS_STORE_ATTEMPTING_GET_REPOS'); - Repos.getReposForUser(maybeData.token, userOrOrgName, function(err, res) { - if (err) { - actionContext.dispatch('ERROR_RECEIVING_REPOS'); - cb(); - } else { - actionContext.dispatch('RECEIVE_REPOS', res.body); - cb(); - } - }, payload.location.query.page); - }; - - //Get orgs for user - var _getOrgsForCurrentUser = function(cb) { - Users.getOrgsForUser(maybeData.token, function(err, res) { - if (err) { - debug(err); - cb(); - } else { - actionContext.dispatch('RECEIVE_DASHBOARD_NAMESPACES', { - orgs: res.body, - user: maybeData.user.username - }); - cb(); - } - }); - }; - - //Get user settings for private repo stats - var _getUserSettings = function(cb) { - Users.getUserSettings(maybeData.token, maybeData.user.username, function(err, res) { - if (err) { - debug(err); - cb(); - } else { - actionContext.dispatch('RECEIVE_PRIVATE_REPOSTATS', res.body); - cb(); - } - }); - }; - - var _doParallelCalls = function() { - async.parallel([ - _getReposForUserOrOrg, - _getOrgsForCurrentUser, - _getUserSettings - ], function(err, results) { - if (err) { - debug(err); - } - return done(); - }); - }; - - //Get Organization by name - var _getOrgByName = function() { - Orgs.getOrg(maybeData.token, payload.params.user, function(err, res) { - if (err) { - debug(err); - } else { - var org = res.body; - if (!_.isEmpty(org)) { - return org; - } - } - }); - return {}; - }; - - //Get user by name - var _getUserByName = function() { - Users.getUser(maybeData.token, payload.params.user, function(err, res) { - if (err) { - debug(err); - } else { - var user = res.body; - if (!_.isEmpty(user)) { - return user; - } - } - }); - return {}; - }; - - if (payload.params.user) { - if (payload.params.user === maybeData.user.username) { - actionContext.dispatch('CURRENT_USER_CONTEXT', { username: payload.params.user }); - _doParallelCalls(); - } else { - async.series([ - function (callback) { - callback(null, _getOrgByName(payload.params.user)); - }, - function (callback) { - callback(null, _getUserByName(payload.params.user)); - } - ], function (err, results) { - if (err) { - debug(err); - } else { - debug('Results of Series Call: ' + JSON.stringify(results)); - //User context is defined as `type`, `name` and `status flag` - actionContext.dispatch('CURRENT_USER_CONTEXT', {username: payload.params.user }); - _getReposForUserOrOrg(done); - } - }); - } - } else { - actionContext.dispatch('CURRENT_USER_CONTEXT', { username: maybeData.user.username }); - _doParallelCalls(); - } - } else { - done(); - } -} diff --git a/app/scripts/actions/navigate/licenses.js b/app/scripts/actions/navigate/licenses.js deleted file mode 100644 index 2735150419..0000000000 --- a/app/scripts/actions/navigate/licenses.js +++ /dev/null @@ -1,57 +0,0 @@ -'use strict'; -var debug = require('debug')('navigate::licenses'); -import async from 'async'; -import request from 'superagent'; -import _ from 'lodash'; -import { - Repositories as Repos, - Notifications, - Orgs, - Users -} from 'hub-js-sdk'; - -function getLicenses({ userID, token, actionContext}, done) { - request(process.env.REGISTRY_API_BASE_URL + '/api/licensing/v3/license/' + userID + '/') - .accept('application/json') - .set('Authorization', 'JWT ' + token) - .end((err, res) => { - if (err) { - done(null, null); - } else { - - let licenses = _.map(res.body.licenses, function(obj) { - return _.merge({}, - obj, - { - orgname: userID - }); - }); - done(null, licenses); - } - }); -} - -export default function licensesFn({ - actionContext, payload, done, maybeData -}){ - - if(maybeData.token) { - Users.getNamespacesForUser(maybeData.token, function(err, res){ - async.map(res.body.namespaces, - function(item, cb) { - getLicenses({ - userID: item, - token: maybeData.token, - actionContext - }, cb); - }, - function(error, results) { - actionContext.dispatch('RECEIVE_LICENSES', _.compact(results)); - done(); - }); - }); - } else { - // user must be logged in; they aren't - done(); - } -} diff --git a/app/scripts/actions/navigate/linkedAccountsSettings.js b/app/scripts/actions/navigate/linkedAccountsSettings.js deleted file mode 100644 index 5f93a8be21..0000000000 --- a/app/scripts/actions/navigate/linkedAccountsSettings.js +++ /dev/null @@ -1,118 +0,0 @@ -'use strict'; - -var debug = require('debug')('navigate::linkedAccounts'); -import async from 'async'; -import { - Builds - } from 'hub-js-sdk'; -import _ from 'lodash'; - -const SOURCES = { - GITHUB: 'github', - BITBUCKET: 'bitbucket' -}; - -export default function linked({actionContext, payload, done, maybeData}){ - if (_.has(maybeData, 'token')) { - - var _checkGithub = function(cb) { - Builds.checkGithub(maybeData.token, function(err, res) { - if(err) { - debug(err); - cb(null, false); - } else { - debug('Github account exists'); - cb(null, true); - } - }); - }; - - var _checkBitbucket = function(cb) { - Builds.checkBitbucket(maybeData.token, function(err, res) { - if(err) { - debug(err); - cb(null, false); - } else { - cb(null, true); - } - }); - }; - - var _getGithubAccount = function(accountExists, cb) { - if(accountExists) { - Builds.getSourceAccount(SOURCES.GITHUB, maybeData.token, function (err, res) { - if (err) { - cb(null, err); - } else { - cb(null, res.body); - } - }); - } else { - cb(null, {detail: 'No associated Github user'}); - } - }; - - var _getBitbucketAccount = function(accountExists, cb) { - if (accountExists) { - Builds.getSourceAccount(SOURCES.BITBUCKET, maybeData.token, function (err, res) { - if(err) { - cb(null, err); - } else { - cb(null, res.body); - } - }); - } else { - Builds.getBitbucketAuthUrl(maybeData.token, function(err, res) { - if (err) { - debug(err); - actionContext.dispatch('BITBUCKET_AUTH_URL_ERROR', err); - } else if (res.ok) { - actionContext.dispatch('RECEIVE_BITBUCKET_AUTH_URL', res.body); - } - }); - cb(null, {detail: 'No associated Bitbucket user'}); - } - }; - - var _wfGetGithubAccount = function(cb) { - async.waterfall([ - _checkGithub, - _getGithubAccount - ], function(err, result) { - debug('Github WF - result', result); - if (!err) { - cb(null, result); - } - }); - }; - - var _wfGetBitbucketAccount = function(cb) { - async.waterfall([ - _checkBitbucket, - _getBitbucketAccount - ], function(err, result) { - debug('Bitbucket WF - result', result); - if (!err) { - cb(null, result); - } - }); - }; - - //Check github and bitbucket and then get the account - async.parallel({ - _wfGetGithubAccount, - _wfGetBitbucketAccount - }, function(err, results) { - debug('results: ', results); - let accounts = { - github: results._wfGetGithubAccount, - bitbucket: results._wfGetBitbucketAccount, - gitlab: {detail: 'No associated GitLab user'} - }; - actionContext.dispatch('RECEIVE_SOURCE_ACCOUNTS', accounts); - return done(); - }); - } else { - done(); - } -} diff --git a/app/scripts/actions/navigate/notificationSettings.js b/app/scripts/actions/navigate/notificationSettings.js deleted file mode 100644 index 787ee68396..0000000000 --- a/app/scripts/actions/navigate/notificationSettings.js +++ /dev/null @@ -1,62 +0,0 @@ -'use strict'; -const debug = require('debug')('navigate::notificationSettings'); -import _ from 'lodash'; -import async from 'async'; -import { - Emails, Notifications - } from 'hub-js-sdk'; - -export default function notificationSettings({actionContext, payload, done, maybeData}){ - if (_.has(maybeData, 'token')) { - var {token, user} = maybeData; - async.parallel({ - subscriptions: function(callback) { - Emails.getEmailSubscriptions(token, user.username, function(err, res){ - if (err) { - debug(err); - callback(); - } else { - callback(null, res.body); - } - }); - }, - notifications: function(callback) { - Notifications.getNotificationSubscriptions(token, function(err, res) { - if (err) { - debug(err); - callback(); - } else { - callback(null, res.body.results); - } - }); - }, - emails: function(callback) { - Emails.getEmailsForUser(token, user.username, function(err, res){ - if (err) { - debug(err); - callback(); - } else { - let emails = res.body.results; - let sortedEmails = _.sortByOrder(emails, ['primary', 'verified'], [false, false]); - callback(null, sortedEmails); - } - }); - } - }, function(err, res) { - let {subscriptions, notifications, emails} = res; - var weeklyDigest, betaGroup; - if (subscriptions) { - weeklyDigest = subscriptions.DockerNewsMailingList; - betaGroup = subscriptions.DockerBetaGroupMailingList; - actionContext.dispatch('RECEIVE_EMAIL_SUBSCRIPTIONS', {weeklyDigest: weeklyDigest, betaGroup: betaGroup}); - } - if (notifications) { - actionContext.dispatch('RECEIVE_NOTIFICATIONS', notifications); - } - actionContext.dispatch('RECEIVE_EMAILS', {emails: emails}); - done(); - }); - } else { - done(); - } -} diff --git a/app/scripts/actions/navigate/orgBilling.js b/app/scripts/actions/navigate/orgBilling.js deleted file mode 100644 index d85e68da1d..0000000000 --- a/app/scripts/actions/navigate/orgBilling.js +++ /dev/null @@ -1,222 +0,0 @@ -'use strict'; - -const debug = require('debug')('navigate::OrgBilling'); -import async from 'async'; -import _ from 'lodash'; -import { - BILLFORWARD_ACCOUNT_ID -} from 'stores/common/Constants.js'; - -import { - Billing, - Users, - Orgs - } from 'hub-js-sdk'; - -function _getOrgPlans(token) { - return (callback) => { - Billing.getPlans(token, 'personal', (err, res) => { - if(err) { - debug(err); - callback(null, []); - } else { - let plansList = res.body; - let sortedPlans = _.sortBy(plansList, 'display_order'); - debug(sortedPlans); - callback(null, sortedPlans); - } - }); - }; -} - -function _getBillingSubscriptions(token, username) { - return (callback) => { - Billing.getBillingSubscriptions(token, username, (err, res) => { - if(!res || res.status === 500) { - debug('SERVER ISSUE: getting subscriptions'); - callback('SERVER ISSUE'); - } else if (err) { - callback(null, res.body); - } else { - debug('GET USER PLANS', res.body); - let subscriptions = res.body; - - // the assumption is that there is at most one subscription right now - let subscription = _.head(subscriptions); - callback(err, subscription); - } - }); - }; -} - -function _getBillingAccount(token, username) { - return (callback) => { - Billing.getBillingAccount(token, username, (err, res) => { - if(!res || res.status === 500) { - debug('SERVER ISSUE: getting billing account info'); - // NOTE: If this is a brand new billing account - set newBilling to true - callback(null, {account: { newBilling: true }}); - } else if (err) { - debug('NO BILLING ACCOUNT CONNECTED'); - // NOTE: If this is a brand new billing account - set newBilling to true - callback(null, {account: { newBilling: true }}); - } else { - debug('GET BILLING ACCOUNT', res.body); - const account = { ...res.body, newBilling: false }; - callback(err, { account, billforwardId: res.header[BILLFORWARD_ACCOUNT_ID] }); - } - }); - }; -} - -function _getBillingInfo(token, username) { - return (callback) => { - Billing.getBillingInfo(token, username, (err, res) => { - if(!res || res.status === 500) { - debug('SERVER ISSUE: getting billing info'); - // NOTE: If this is a brand new billing profile - set newBilling to true - callback(null, { newBilling: true }); - } else if (err) { - debug('NO BILLING INFO CONNECTED'); - // NOTE: If this is a brand new billing profile - set newBilling to true - callback(null, { newBilling: true }); - } else { - debug('GET BILLING INFO', res.body); - callback(err, { ...res.body, newBilling: false }); - } - }); - }; -} - -function _getBillingInvoices(token, username) { - return (callback) => { - Billing.getBillingInvoices(token, username, (err, res) => { - if(err) { - debug('NO BILLING ACCOUNT INVOICES'); - callback(null, []); - } else { - debug('GET BILLING INVOICES', res.body); - callback(err, res.body); - } - }); - }; -} - -//Get orgs for user -function _getOrgsForCurrentUser(token) { - return (callback) => { - Users.getOrgsForUser(token, function(err, res) { - if (err) { - debug(err); - callback(); - } else { - debug('GET Orgs for current User', res.body); - callback(null, res.body); - } - }); - }; -} - -//Get org's settings since we are in the organization's home -function _getOrgSettings(token, username) { - return (callback) => { - Orgs.getOrg(token, username, function (err, res) { - if (err) { - callback(); - } else { - debug('GET Orgs Settings', res.body); - callback(null, res.body); - } - }); - }; -} - -//Get user settings for private repo stats -var _getOrgPrivateRepoSettings = function(ac, token, username) { - return (cb) => { - Orgs.getOrgSettings(token, username, function (err, res) { - if (err) { - debug(err); - ac.dispatch('PRIVATE_REPOSTATS_NO_PERMISSIONS', err); - cb(null, err); - } else { - ac.dispatch('RECEIVE_PRIVATE_REPOSTATS', res.body); - cb(null, res.body); - } - }); - }; -}; - -var _getNamespaces = function(actionContext, token, profileuser) { - return (callback) => { - Users.getNamespacesForUser(token, function(err, res) { - if (err) { - callback(); - } else { - callback(null, res.body); - actionContext.dispatch('CREATE_REPO_RECEIVE_NAMESPACES', { - namespaces: res.body, - selectedNamespace: profileuser - }); - } - }); - }; -}; - -export default function billingOrgPlans({actionContext, payload, done, maybeData}){ - if (maybeData.token && maybeData.user) { - let {token, user} = maybeData; - let username = payload.params.user; - actionContext.dispatch('RESET_BILLING_PLANS'); - /* - NOTE: - None of the functions should pass an error into the callback or else it will - kill the rest of the calls and return before we're able to fetch all the data - */ - async.parallel({ - allPlans: _getOrgPlans(token), - userPlan: _getBillingSubscriptions(token, username), - accountInfo: _getBillingAccount(token, username), - billingInfo: _getBillingInfo(token, username), - invoiceList: _getBillingInvoices(token, username), - getOrgs: _getOrgsForCurrentUser(token), - getOrgSettings: _getOrgSettings(token, username), - getPrivateRepoStats: _getOrgPrivateRepoSettings(actionContext, token, username), - getNamespaces: _getNamespaces(actionContext, token, user.username) - }, function(err, results){ - const { - allPlans, - userPlan, - accountInfo, - billingInfo, - invoiceList, - getOrgs, - getOrgSettings - } = results; - debug('BILLING PLANS', results); - const gateway = accountInfo && accountInfo.account && accountInfo.account.payment_gateway; - const billforwardId = accountInfo && accountInfo.billforwardId; - - actionContext.dispatch('CURRENT_USER_CONTEXT', { username: username }); - actionContext.dispatch('RECEIVE_BILLING_PLANS', { - plansList: allPlans - }); - actionContext.dispatch('RECEIVE_BILLING_INFO', { - billingInfo: billingInfo, - accountInfo: accountInfo && accountInfo.account, - currentPlan: userPlan, - gateway, - billforwardId - }); - actionContext.dispatch('RECEIVE_INVOICES', {invoices: invoiceList}); - actionContext.dispatch('RECEIVE_DASHBOARD_NAMESPACES', { - orgs: getOrgs, - user: user.username - }); - actionContext.dispatch('RECEIVE_ORGANIZATION', getOrgSettings); - return done(); - }); - } else { - done(); - } -} diff --git a/app/scripts/actions/navigate/orgDashTeams.js b/app/scripts/actions/navigate/orgDashTeams.js deleted file mode 100644 index 41987a8e12..0000000000 --- a/app/scripts/actions/navigate/orgDashTeams.js +++ /dev/null @@ -1,146 +0,0 @@ -'use strict'; -var debug = require('debug')('navigate orgHome'); -import async from 'async'; -import _ from 'lodash'; -import { - Repositories as Repos, - Notifications, - Orgs, - Users -} from 'hub-js-sdk'; - -export default function home({actionContext, payload, done, maybeData}){ - if (_.has(maybeData, 'token')) { - const currentOrg = payload.params.user; - - //Get orgs for user - var _getOrgsForCurrentUser = function(cb) { - Users.getOrgsForUser(maybeData.token, function(err, res) { - if (err) { - debug(err); - cb(); - } else { - actionContext.dispatch('RECEIVE_DASHBOARD_NAMESPACES', { - orgs: res.body, - user: maybeData.user.username - }); - cb(); - } - }); - }; - - //Get user settings for private repo stats - var _getOrgPrivateRepoSettings = function(cb) { - Orgs.getOrgSettings(maybeData.token, currentOrg, function(err, res) { - if (err) { - debug(err); - actionContext.dispatch('PRIVATE_REPOSTATS_NO_PERMISSIONS', err); - actionContext.dispatch('TEAM_READ_ONLY', true); - cb(); - } else { - actionContext.dispatch('RECEIVE_PRIVATE_REPOSTATS', res.body); - actionContext.dispatch('TEAM_READ_ONLY', false); - cb(); - } - }); - }; - - //Get Teams for an org - var _getTeamsForOrg = function(cb) { - Orgs.getTeams(maybeData.token, currentOrg, function(err, res) { - if (err) { - debug(err); - cb(); - } else { - actionContext.dispatch('RECEIVE_DASHBOARD_ORG_TEAMS', res.body); - cb(); - } - }); - }; - - var _getNamespaces = function(cb) { - Users.getNamespacesForUser(maybeData.token, function(err, res) { - if (err) { - cb(); - } else { - cb(null, res.body); - actionContext.dispatch('CREATE_REPO_RECEIVE_NAMESPACES', { - namespaces: res.body, - selectedNamespace: maybeData.user.username - }); - } - }); - }; - - const currentTeam = payload.location.query.team; - var _getTeam = function(cb) { - if (currentTeam) { - Orgs.getTeam(maybeData.token, currentOrg, currentTeam, function(err, res) { - if (err) { - actionContext.dispatch('ORG_DASHBOARD_MEMBERS_ERROR', err); - cb(null, err); - } else { - actionContext.dispatch('RECEIVE_DASHBOARD_ORG_TEAM', res.body); - cb(null, res.body); - } - }); - } else { - cb(null, null); - } - }; - - var _getMembers = function(cb) { - if (currentTeam) { - Orgs.getMembers(maybeData.token, currentOrg, currentTeam, function(err, res) { - if (err) { - actionContext.dispatch('ORG_DASHBOARD_MEMBERS_ERROR', err); - cb(null, err); - } else { - actionContext.dispatch('RECEIVE_DASHBOARD_TEAM_MEMBERS', res.body); - cb(null, res.body); - } - }); - } else { - cb(null, null); - } - }; - - //This is executed only for the currently logged in user, so put in starred, contributed only here - var _doParallelCalls = function() { - async.parallel([ - _getOrgsForCurrentUser, - _getOrgPrivateRepoSettings, - _getTeamsForOrg, - _getNamespaces, - _getTeam, - _getMembers - ], function(err, results) { - if (err) { - debug(err); - } - return done(); - }); - }; - - //Get Organization by name - var _getOrgByName = function(name, cb) { - Orgs.getOrg(maybeData.token, name, function(err, res) { - if (err) { - debug(err); - cb({}); - } else { - var org = res.body; - cb(org); - } - }); - }; - - actionContext.dispatch('CURRENT_USER_CONTEXT', { - username: payload.params.user - }); - _doParallelCalls(); - - } else { - done(); - } -} diff --git a/app/scripts/actions/navigate/orgHome.js b/app/scripts/actions/navigate/orgHome.js deleted file mode 100644 index dc2a9bd106..0000000000 --- a/app/scripts/actions/navigate/orgHome.js +++ /dev/null @@ -1,143 +0,0 @@ -'use strict'; -var debug = require('debug')('navigate orgHome'); -import async from 'async'; -import _ from 'lodash'; -import { - Repositories as Repos, - Notifications, - Orgs, - Users -} from 'hub-js-sdk'; - -export default function home({actionContext, payload, done, maybeData}){ - if (_.has(maybeData, 'token')) { - - //Get repos for user or org - var _getReposForUserOrOrg = function(cb, userType) { - actionContext.dispatch('DASHBOARD_REPOS_STORE_ATTEMPTING_GET_REPOS'); - Repos.getReposForUser(maybeData.token, payload.params.user, function(err, res) { - if (err) { - actionContext.dispatch('ERROR_RECEIVING_REPOS'); - cb(); - } else { - actionContext.dispatch('RECEIVE_REPOS', res.body); - cb(); - } - }, payload.location.query.page); - }; - - //Get contributed repos - var _getReposByFilterTypeContrib = function(cb) { - var username = maybeData.user.username; - Repos.getContributedReposForUser(maybeData.token, username, function (err, res) { - if (err) { - cb(); - } else { - var resultPayload = {type: 'contrib', results: res.body.results}; - actionContext.dispatch('RECEIVE_CONTRIB', resultPayload); - cb(); - } - }); - }; - - //Get orgs for user - var _getOrgsForCurrentUser = function(cb) { - Users.getOrgsForUser(maybeData.token, function(err, res) { - if (err) { - debug(err); - cb(); - } else { - actionContext.dispatch('RECEIVE_DASHBOARD_NAMESPACES', { - orgs: res.body, - user: maybeData.user.username - }); - cb(); - } - }); - }; - - //Get user settings for private repo stats - var _getOrgPrivateRepoSettings = function(cb) { - Orgs.getOrgSettings(maybeData.token, payload.params.user, function(err, res) { - if (err) { - debug(err); - actionContext.dispatch('PRIVATE_REPOSTATS_NO_PERMISSIONS', err); - actionContext.dispatch('TEAM_READ_ONLY', true); - cb(); - } else { - actionContext.dispatch('RECEIVE_PRIVATE_REPOSTATS', res.body); - actionContext.dispatch('TEAM_READ_ONLY', false); - cb(); - } - }); - }; - - //Get org's settings since we are in the organization's home - var _getOrgSettings = function(cb) { - Orgs.getOrg(maybeData.token, payload.params.user, function (err, res) { - if (err) { - cb(); - } else { - actionContext.dispatch('RECEIVE_ORGANIZATION', res.body); - cb(); - } - }); - }; - - var _getNamespaces = function(cb) { - Users.getNamespacesForUser(maybeData.token, function(err, res) { - if (err) { - cb(); - } else { - cb(null, res.body); - actionContext.dispatch('CREATE_REPO_RECEIVE_NAMESPACES', { - namespaces: res.body, - selectedNamespace: maybeData.user.username - }); - } - }); - }; - - //This is executed only for the currently logged in user, so put in starred, contributed only here - var _doParallelCalls = function() { - async.parallel([ - _getReposForUserOrOrg, - _getOrgsForCurrentUser, - _getReposByFilterTypeContrib, - _getOrgSettings, - _getOrgPrivateRepoSettings, - _getNamespaces - ], function(err, results) { - if (err) { - debug(err); - } - return done(); - }); - }; - - //Get Organization by name - var _getOrgByName = function(name, cb) { - Orgs.getOrg(maybeData.token, name, function(err, res) { - if (err) { - debug(err); - cb({}); - } else { - var org = res.body; - cb(org); - } - }); - }; - - if (payload.params.user) { - actionContext.dispatch('CURRENT_USER_CONTEXT', { username: payload.params.user }); - _doParallelCalls(); - } else { - debug('mark 5'); - actionContext.dispatch('CURRENT_USER_CONTEXT', { username: payload.params.user }); - _doParallelCalls(); - } - } else { - debug('mark 6'); - done(); - } -} diff --git a/app/scripts/actions/navigate/orgSettings.js b/app/scripts/actions/navigate/orgSettings.js deleted file mode 100644 index e0ff148a60..0000000000 --- a/app/scripts/actions/navigate/orgSettings.js +++ /dev/null @@ -1,66 +0,0 @@ -'use strict'; - -import _ from 'lodash'; -import { - Users - } from 'hub-js-sdk'; -import async from 'async'; -var debug = require('debug')('navigate::orgSettings'); - -export default function orgs({actionContext, payload, done, maybeData}){ - debug('Organization Settings Navigate Token -> ' + maybeData.token); - debug('ORG SETTINGS PAYLOAD', payload); - let orgName = payload.params.user; - if (_.has(maybeData, 'token')) { - async.parallel({ - getOrgs: function(callback) { - Users.getOrgsForUser(maybeData.token, function(getErr, getRes) { - if (getErr) { - debug(getErr); - callback(); - } else { - actionContext.dispatch('RECEIVE_DASHBOARD_NAMESPACES', { - orgs: getRes.body, - user: maybeData.user.username - }); - actionContext.dispatch('CURRENT_USER_ORGS', getRes.body); - actionContext.dispatch('SELECT_ORGANIZATION', orgName); - actionContext.dispatch('CURRENT_USER_CONTEXT', { username: orgName }); - callback(null, getRes.body); - } - }); - }, - getUserSettings: function(callback) { - let username = payload.params.user; - Users.getUserSettings(maybeData.token, username, function(getErr, getRes) { - if (getErr){ - debug(getErr); - callback(); - } else { - let is_private = (getRes.default_repo_visibility); - actionContext.dispatch('CREATE_REPO_UPDATE_FIELD_WITH_VALUE', {fieldKey: 'is_private', fieldValue: is_private}); - actionContext.dispatch('RECEIVE_PRIVATE_REPOSTATS', getRes.body); - callback(null, getRes.body); - } - }); - }, - getNamespaces: function(callback) { - Users.getNamespacesForUser(maybeData.token, function(err, res) { - if (err) { - callback(); - } else { - callback(null, res.body); - actionContext.dispatch('CREATE_REPO_RECEIVE_NAMESPACES', { - namespaces: res.body, - selectedNamespace: maybeData.user.username - }); - } - }); - } - }, function(err, res){ - done(); - }); - } else { - done(); - } -} diff --git a/app/scripts/actions/navigate/orgSummary.js b/app/scripts/actions/navigate/orgSummary.js deleted file mode 100644 index e385c69e4a..0000000000 --- a/app/scripts/actions/navigate/orgSummary.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; - -import _ from 'lodash'; -import { - Users - } from 'hub-js-sdk'; -var debug = require('debug')('navigate::orgSummary'); - -export default function orgs({actionContext, payload, done, maybeData}){ - debug('Organization Settings Navigate Token -> ' + maybeData.token); - if (_.has(maybeData, 'token')) { - Users.getOrgsForUser(maybeData.token, function(err, res) { - if (err) { - debug(err); - done(); - } else { - actionContext.dispatch('CURRENT_USER_ORGS', res.body); - done(); - } - }); - } else { - done(); - } -} diff --git a/app/scripts/actions/navigate/repo.js b/app/scripts/actions/navigate/repo.js deleted file mode 100644 index 6680ef4b72..0000000000 --- a/app/scripts/actions/navigate/repo.js +++ /dev/null @@ -1,100 +0,0 @@ -'use strict'; - -import _ from 'lodash'; -import async from 'async'; -import { PENDING_DELETE } from 'common/enums/RepoStatus'; -import { - Repositories as Repos, - Autobuilds -} from 'hub-js-sdk'; - -export default function repo({actionContext, payload, done, maybeData}){ - var token; - if (_.has(maybeData, 'token')) { - token = maybeData.token; - } else { - token = ''; - } - - var namespace = payload.params.user; - if(payload.params.user === '_') { - namespace = 'library'; - } - var repoShortName = namespace + '/' + payload.params.splat; - - //1. Get repository details - //2. If successful, set valid repo and pass it along for the next set of calls - //3. If not valid, set repo to be not valid and dispatch repo not found - var _getRepo = function(cb) { - Repos.getRepo(token, repoShortName, function(err, res) { - var repoInfo = {}; - let status; - if (res && res.body) { - status = res.body.status; - } - - if (err || status === PENDING_DELETE) { - repoInfo.error = err; - repoInfo.isValid = false; - cb(null, repoInfo); - actionContext.dispatch('REPO_NOT_FOUND', err); - } else { - repoInfo.info = res.body; - actionContext.dispatch('RECEIVE_REPOSITORY', res.body); - repoInfo.isValid = true; - cb(null, repoInfo); - } - }); - }; - - var _getRepoDetails = function(repoInfo, cb) { - if (repoInfo.isValid) { - async.parallel([ - function(callback) { - Repos.getCommentsForRepo(token, repoShortName, function(err, res) { - if (err) { - callback(err); - } else { - callback(null, res.body); - } - }, 1); - }, function(callback) { - if (repoInfo.info.is_automated) { - Autobuilds.getAutomatedBuildSettings(token, namespace, payload.params.splat, function (err, res) { - if (err) { - actionContext.dispatch('AUTOBUILD_REPO_NOT_FOUND'); - callback(null); - } else { - callback(null, res.body); - } - }); - } else { - callback(null); - } - } - ], - function(error, results) { - if (error) { - cb(error); - } else { - cb(null, results); - } - }); - } else { - cb('repo not found'); - } - }; - - async.waterfall([ - _getRepo, - _getRepoDetails - ], function(e, finalResults) { - if (finalResults) { - actionContext.dispatch('RECEIVE_REPO_COMMENTS', finalResults[0]); - if (finalResults[1]) { - actionContext.dispatch('RECEIVE_AUTOBUILD_SETTINGS', finalResults[1]); - } - } - done(); - }); -} diff --git a/app/scripts/actions/navigate/repoDetailsScannedTag.js b/app/scripts/actions/navigate/repoDetailsScannedTag.js deleted file mode 100644 index dd7e9803d4..0000000000 --- a/app/scripts/actions/navigate/repoDetailsScannedTag.js +++ /dev/null @@ -1,114 +0,0 @@ -'use strict'; - -import { parallel } from 'async'; -import { PENDING_DELETE } from 'common/enums/RepoStatus'; -import has from 'lodash/object/has'; -import merge from 'lodash/object/merge'; -import { Repositories as Repos } from 'hub-js-sdk'; -import { - RECEIVE_REPO, - RECEIVE_SCANNED_TAG_DATA, - ERROR -} from 'reduxConsts'; -const debug = require('debug')('navigate::repoDetailsScannedTagData'); -import request from 'superagent'; -import { normalize, arrayOf } from 'normalizr'; -import { scan } from 'normalizers'; - -const getRepo = ({maybeToken, actionContext, user, splat}) => (callback) => { - Repos.getRepo(maybeToken, `${user}/${splat}`, function(err, res) { - let status; - if (res && res.body) { - status = res.body.status; - } - - if (err || status === PENDING_DELETE) { - actionContext.dispatch('REPO_NOT_FOUND', err); - return callback(err); - } else { - return callback(null, res.body); - } - }); -}; - -/* - * Get nautilus scan info for the tag. - * TODO: Once this API is in it's final form for the jan release, move it to the SDK - */ -const getScanForTag = ({actionContext, maybeToken, payload, user, splat, tagname, done}) => (callback) => { - const namespace = user; - const name = splat; - const req = request.get(`${process.env.NAUTILUS_API_BASE_URL}/repositories/result?namespace=${namespace}&reponame=${name}&tag=${tagname}&detailed=1`); - if (maybeToken) { - req.set('Authorization', 'JWT ' + maybeToken); - } - req.timeout(7000); - req.end((err, res) => { - if (err) { - // NOTE: Suffixing the dispatch type with _STATUS means the status - // reducer will record this in the same way as our SDK calls - // via the middleware. - // When we move this to the SDK, the error will be dispatched automatically - actionContext.reduxStore.dispatch({ - type: `${RECEIVE_SCANNED_TAG_DATA}_STATUS`, - payload: { - status: ERROR, - statusKey: ['getScanForTag', namespace, name, tagname], - error: err - }, - error: true - }); - return callback(err); - } else { - // The API response contains a 'scan' resource within an object - // inside 'scan_details' - const { scan_details, image: { reponame, tag } } = res.body; - const { latest_scan_status } = res.body; - const result = { latest_scan_status, reponame, tag, ...scan_details }; - const normalized = normalize(result, scan); - return callback(null, normalized); - } - }); -}; - -export default function repoDetailsScannedTag({actionContext, payload, done, maybeData}){ - let token = ''; - if (has(maybeData, 'token')) { - token = maybeData.token; - } - const args = { - actionContext, - maybeToken: token, - user: payload.params.user, - splat: payload.params.splat, - tagname: payload.params.tagname - }; - - parallel({ - repo: getRepo(args), - tagScan: getScanForTag(args) - }, function(err, res){ - if (err) { - actionContext.dispatch('REPO_NOT_FOUND', err); - } else { - const { repo, tagScan } = res; - /* REPOS */ - //required for repository page header to display - actionContext.dispatch('RECEIVE_REPOSITORY', repo); - // We also need to dispatch to Redux; this will store the current repo - // within the repos reducer allowing us to find the namespace and repo - // name for the current route. - actionContext.reduxStore.dispatch({ - type: RECEIVE_REPO, - payload: repo - }); - - /* SCANS */ - actionContext.reduxStore.dispatch({ - type: RECEIVE_SCANNED_TAG_DATA, - payload: tagScan - }); - } - done(); - }); -} diff --git a/app/scripts/actions/navigate/repoDetailsTags.js b/app/scripts/actions/navigate/repoDetailsTags.js deleted file mode 100644 index 576505e142..0000000000 --- a/app/scripts/actions/navigate/repoDetailsTags.js +++ /dev/null @@ -1,147 +0,0 @@ -'use strict'; -const debug = require('debug')('navigate::repo'); -import { parallel } from 'async'; -import { PENDING_DELETE } from 'common/enums/RepoStatus'; -import has from 'lodash/object/has'; -import merge from 'lodash/object/merge'; -import request from 'superagent'; -import { - RECEIVE_NAUTILUS_TAGS_FOR_REPOSITORY, - RECEIVE_TAGS_FOR_REPOSITORY, - RECEIVE_REPO -} from 'reduxConsts.js'; -import { normalize, arrayOf } from 'normalizr'; -import { tag } from 'normalizers'; -import { - Repositories as Repos -} from 'hub-js-sdk'; - -const getRepo = ({maybeToken, actionContext, user, splat}) => (callback) => { - Repos.getRepo(maybeToken, `${user}/${splat}`, function(err, res) { - let status; - if (res && res.body) { - status = res.body.status; - } - - if (err || status === PENDING_DELETE) { - return callback(err); - } else { - return callback(null, res.body); - } - }); -}; - -// getTagsForRepo uses the hub API for loading tag information. This is used to -// show information about tags that are not scanned. -// -// We use this and the nautilus API because each API has incomplete information: -// - The nautilus API has vulnerability information -// - This API has the image size -// -// NOTE: This dispatches to Redux reducers and fluxible stores in the final callback -const getTagsForRepo = ({actionContext, maybeToken, user, splat}) => (callback) => { - const namespace = user; - const reponame = splat; - Repos.getTagsForRepo(maybeToken, `${user}/${splat}`, function(err, res) { - if (err) { - return callback(err); - } - const { results } = res.body; - // TODO: Assert normalize works as expected via jest/mocha - const tags = normalize(results, arrayOf(tag)); - return callback(null, { namespace, reponame, tags }); - }); -}; - -// getNautilusTagsForRepo uses the nautilus API to load tags and their -// vulnerability information via the nautilus API. -// -// NOTE: This dispatches to Redux reducers, not fluxible stores -const getNautilusTagsForRepo = ({actionContext, maybeToken, user, splat}) => (callback) => { - const namespace = user; - const reponame = splat; - const req = request.get(`${process.env.NAUTILUS_API_BASE_URL}/repositories/summaries/${namespace}/${reponame}`); - if (maybeToken) { - req.set('Authorization', 'JWT ' + maybeToken); - } - req.timeout(7000); - req.end((err, res) => { - if (err) { - // Nautilus call does NOT trigger an error page - return callback(null, null); - } - // TODO: Assert normalize works as expected via jest/mocha - const tags = normalize( - res.body, - arrayOf(tag), - { - // TODO: Add records - // NOTE: The nautius API uses a field called 'tag' to represent the - // tag name, whereas the HUB api uses 'name'. - // - // Our record, frontend code and normalizr key expects us to use - // the 'name' field. This normalizes the record to tag. - assignEntity: (obj, key, val) => { - obj[key] = val; - if (key === 'tag') { - obj.name = val; - delete obj.tag; - } - } - } - ); - return callback(null, { namespace, reponame, tags }); - }); -}; - -export default function repoDetailsTags({actionContext, payload, done, maybeData}) { - debug('maybeData:', maybeData); - let token = ''; - if (has(maybeData, 'token')) { - token = maybeData.token; - } - const { user, splat } = payload.params; - const args = { - actionContext, - maybeToken: token, - user, - splat - }; - - parallel({ - repo: getRepo(args), - tags: getTagsForRepo(args), - scans: getNautilusTagsForRepo(args) - }, (err, res) => { - if (err) { - // Tags or repo error - actionContext.dispatch('REPO_NOT_FOUND', err); - } else { - const { repo, tags, scans } = res; - /* REPO */ - actionContext.dispatch('RECEIVE_REPOSITORY', repo); - // We also need to dispatch to Redux; this will store the current repo - // within the repos reducer allowing us to find the namespace and repo - // name for the current route. - actionContext.reduxStore.dispatch({ - type: RECEIVE_REPO, - payload: repo - }); - - /* TAGS */ - actionContext.reduxStore.dispatch({ - type: RECEIVE_TAGS_FOR_REPOSITORY, - payload: tags - }); - - /* SCANS */ - if (scans) { - actionContext.reduxStore.dispatch({ - type: RECEIVE_NAUTILUS_TAGS_FOR_REPOSITORY, - payload: scans - }); - } - } - done(); - }); -} diff --git a/app/scripts/actions/navigate/repoOfficial.js b/app/scripts/actions/navigate/repoOfficial.js deleted file mode 100644 index 9fcf0e3dba..0000000000 --- a/app/scripts/actions/navigate/repoOfficial.js +++ /dev/null @@ -1,48 +0,0 @@ -'use strict'; - -import _ from 'lodash'; -import async from 'async'; -import { PENDING_DELETE } from 'common/enums/RepoStatus'; -import { - Repositories as Repos -} from 'hub-js-sdk'; - -export default function repo({actionContext, payload, done, maybeData}){ - var token; - if (_.has(maybeData, 'token')) { - token = maybeData.token; - } else { - token = ''; - } - var repoShortName = 'library/' + payload.params.splat; - async.series([ - function(callback) { - Repos.getRepo(token, repoShortName, function(err, res) { - let status; - if (res && res.body) { - status = res.body.status; - } - - if (err || status === PENDING_DELETE) { - actionContext.dispatch('REPO_NOT_FOUND', err); - callback(err); - } else { - actionContext.dispatch('RECEIVE_REPOSITORY', res.body); - callback(null, res.body); - } - }); - }, function(callback) { - Repos.getCommentsForRepo(token, repoShortName, function(err, res) { - if (err) { - callback(err); - } else { - actionContext.dispatch('RECEIVE_REPO_COMMENTS', res.body); - callback(null, res.body); - } - }); - } - ], - function(error, results) { - done(); - }); -} diff --git a/app/scripts/actions/navigate/repoSettings.js b/app/scripts/actions/navigate/repoSettings.js deleted file mode 100644 index 0af30fd929..0000000000 --- a/app/scripts/actions/navigate/repoSettings.js +++ /dev/null @@ -1,67 +0,0 @@ -'use strict'; -const debug = require('debug')('navigate::repo'); -import { parallel, waterfall } from 'async'; -import { PENDING_DELETE } from 'common/enums/RepoStatus'; -import _ from 'lodash'; -import { - Repositories as Repos, - Users -} from 'hub-js-sdk'; - -function getRepo({maybeToken, actionContext, user, splat}) { - return function(callback){ - Repos.getRepo(maybeToken, `${user}/${splat}`, function(err, res) { - let status; - if (res && res.body) { - status = res.body.status; - } - - if (err || status === PENDING_DELETE) { - actionContext.dispatch('REPO_NOT_FOUND', res.body); - return callback(null, null); - } else { - actionContext.dispatch('RECEIVE_REPOSITORY', res.body); - return callback(null, res.body); - } - }); - }; -} - -function handleGetPrivateRepoStats({maybeToken, user, actionContext}) { - return function(repoDetails, callback) { - if (repoDetails) { - Users.getUserSettings(maybeToken, user, function (err, res) { - if (err) { - callback(); - } else { - actionContext.dispatch('RECEIVE_PRIVATE_REPOSTATS', res.body); - callback(); - } - }); - } else { - callback(null, null); - } - }; -} - -export default function repoSettingsMain({actionContext, payload, done, maybeData}){ - debug('maybeData:', maybeData); - if (_.has(maybeData, 'token')) { - let args = { - actionContext, - maybeToken: maybeData.token, - user: payload.params.user, - splat: payload.params.splat - }; - - waterfall([ - getRepo(args), - handleGetPrivateRepoStats(args) - ], function(err, res){ - done(); - }); - } else { - actionContext.dispatch('REPO_NOT_FOUND', null); - done(); - } -} diff --git a/app/scripts/actions/navigate/repoSettingsCollaborators.js b/app/scripts/actions/navigate/repoSettingsCollaborators.js deleted file mode 100644 index d6b5878d91..0000000000 --- a/app/scripts/actions/navigate/repoSettingsCollaborators.js +++ /dev/null @@ -1,97 +0,0 @@ -'use strict'; -const debug = require('debug')('navigate::repo'); -import { parallel } from 'async'; -import { PENDING_DELETE } from 'common/enums/RepoStatus'; -import _ from 'lodash'; -import { - Repositories as Repos, - Orgs -} from 'hub-js-sdk'; - -function getRepo({maybeToken, actionContext, user, splat}) { - return function(callback){ - Repos.getRepo(maybeToken, `${user}/${splat}`, function(err, res) { - let status; - if (res && res.body) { - status = res.body.status; - } - - if (err || status === PENDING_DELETE) { - actionContext.dispatch('REPO_NOT_FOUND', null); - return callback(err); - } - actionContext.dispatch('RECEIVE_REPOSITORY', res.body); - return callback(); - }); -}; -} - -// GET's the collaborators for a user repo (which should be individuals) -function getCollaborators({maybeToken, actionContext, user, splat}) { - return function(cb) { - Repos.getCollaboratorsForRepo(maybeToken, `${user}/${splat}`, (err, res) => { - if(err) { - // 'Org repositories do not have collaborators.' - actionContext.dispatch('COLLAB_RECEIVE_COLLABORATORS', {}); - } else { - actionContext.dispatch('COLLAB_RECEIVE_COLLABORATORS', res.body); - } - cb(); - }); - }; -} - - //GET's the collaborators for an organization repo (which should be teams) -function getTeamCollaborators({maybeToken, actionContext, user, splat}) { - return function(cb) { - Repos.getTeamCollaboratorsForRepo(maybeToken, `${user}/${splat}`, (err, res) => { - if (err) { - // 'User repository does not have any teams yet' - actionContext.dispatch('COLLAB_RECEIVE_TEAMS', {}); - } else { - actionContext.dispatch('COLLAB_RECEIVE_TEAMS', res.body); - } - cb(); - }); - }; -} - -// GET's all teams for the organization -function getOrgTeams({maybeToken, actionContext, user, splat}) { - return function(cb) { - Orgs.getTeams(maybeToken, user, (err, res) => { - if (err) { - // 'No such organization' - actionContext.dispatch('COLLAB_RECEIVE_TEAMS', {}); - actionContext.dispatch('COLLAB_RECEIVE_ALL_TEAMS', {results: []}); - } else { - actionContext.dispatch('COLLAB_RECEIVE_ALL_TEAMS', res.body); - } - cb(); - }); - }; -} - -export default function repoSettingsMain({actionContext, payload, done, maybeData}){ - debug('maybeData:', maybeData); - if (_.has(maybeData, 'token')) { - let args = { - actionContext, - maybeToken: maybeData.token, - user: payload.params.user, - splat: payload.params.splat - }; - - parallel([ - getRepo(args), - getCollaborators(args), - getTeamCollaborators(args), - getOrgTeams(args) - ], function(err, res){ - done(); - }); - } else { - actionContext.dispatch('REPO_NOT_FOUND', null); - done(); - } -} diff --git a/app/scripts/actions/navigate/resetPass.js b/app/scripts/actions/navigate/resetPass.js deleted file mode 100644 index fa68db137a..0000000000 --- a/app/scripts/actions/navigate/resetPass.js +++ /dev/null @@ -1,6 +0,0 @@ -'use strict'; - -export default function resetPass({actionContext, payload, done, maybeData}){ - actionContext.dispatch('CHANGE_PASS_CLEAR'); - done(); -} diff --git a/app/scripts/actions/navigate/search.js b/app/scripts/actions/navigate/search.js deleted file mode 100644 index d0652a2ce4..0000000000 --- a/app/scripts/actions/navigate/search.js +++ /dev/null @@ -1,44 +0,0 @@ -'use strict'; -var debug = require('debug')('navigate::search'); - -import { - Search -} from 'hub-js-sdk'; - -export default function search({actionContext, payload, done, maybeData}){ - debug('Hit /search:: Query = ' + JSON.stringify(payload.location.query)); - debug('Searching for: ' + payload.location.query.q); - //the filter param values are `0` because the python api accepts either `0` or `False`, we decided to use `0` - var searchQueryParams = { - query: payload.location.query.q || '', - page: payload.location.query.page || '', - isAutomated: payload.location.query.isAutomated || 0, - isOfficial: payload.location.query.isOfficial || 0, - starCount: payload.location.query.starCount || 0, - pullCount: payload.location.query.pullCount || 0 - }; - - //TODO: Maybe we should have a single dispatch here? - actionContext.dispatch('SUBMIT_SEARCH_QUERY', searchQueryParams.query); - actionContext.dispatch('UPDATE_SEARCH_PAGE', searchQueryParams.page); - actionContext.dispatch('UPDATE_SEARCH_OTHERFILTERS', searchQueryParams); - - //This is to search repositories - Search.searchRepos(maybeData.token, searchQueryParams, function(err, res) { - if (err) { - debug(err); - actionContext.dispatch('SEARCH_ERROR', err); - done(); - } else { - debug(res); - var queryResult = res.body; - //Query Result details (for paging) - if (queryResult) { - actionContext.dispatch('PROCESS_SEARCH_RESULTS', queryResult); - done(); - } else { - done(); - } - } - }); -} diff --git a/app/scripts/actions/navigate/serverBilling.js b/app/scripts/actions/navigate/serverBilling.js deleted file mode 100644 index 00f6fcfb78..0000000000 --- a/app/scripts/actions/navigate/serverBilling.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict'; -var debug = require('debug')('navigate::home'); -import async from 'async'; -import _ from 'lodash'; -import { - Users -} from 'hub-js-sdk'; - -export default function enterpriseTrial({actionContext, payload, done, maybeData}){ - - if(payload.location.query.partnervalue) { - actionContext.dispatch('ENTERPRISE_PARTNER_RECEIVE_CODE', { - code: payload.location.query.partnervalue - }); - } - - if(_.has(maybeData, 'token')){ - Users.getNamespacesForUser(maybeData.token, function(err, res) { - if (err) { - done(); - } else { - if(res.body && res.body.namespaces) { - actionContext.dispatch('ENTERPRISE_PAID_RECEIVE_ORGS', res.body.namespaces); - } - done(); - } - }); - } else { - done(); - } -} diff --git a/app/scripts/actions/navigate/serverTrial.js b/app/scripts/actions/navigate/serverTrial.js deleted file mode 100644 index 7aae21f284..0000000000 --- a/app/scripts/actions/navigate/serverTrial.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict'; -var debug = require('debug')('navigate::home'); -import async from 'async'; -import _ from 'lodash'; -import { - Users -} from 'hub-js-sdk'; - -export default function enterpriseTrial({actionContext, payload, done, maybeData}){ - - if(payload.location.query.partnervalue) { - actionContext.dispatch('ENTERPRISE_PARTNER_RECEIVE_CODE', { - code: payload.location.query.partnervalue - }); - } - - if(_.has(maybeData, 'token')){ - Users.getNamespacesForUser(maybeData.token, function(err, res) { - if (err) { - done(); - } else { - if(res.body && res.body.namespaces) { - actionContext.dispatch('ENTERPRISE_TRIAL_RECEIVE_ORGS', res.body.namespaces); - } - done(); - } - }); - } else { - done(); - } -} diff --git a/app/scripts/actions/navigate/serverTrialSuccess.js b/app/scripts/actions/navigate/serverTrialSuccess.js deleted file mode 100644 index 6c4bc1f200..0000000000 --- a/app/scripts/actions/navigate/serverTrialSuccess.js +++ /dev/null @@ -1,39 +0,0 @@ -'use strict'; -const debug = require('debug')('navigate::serverTrialSuccess'); -import merge from 'lodash/object/merge'; -import find from 'lodash/collection/find'; -import { Billing } from 'hub-js-sdk'; - -export default function serverTrialSuccess({ - actionContext, payload, done, maybeData -}){ - const { namespace } = payload.location.query; - if(maybeData.token) { - Billing.getLicensesForNamespace(maybeData.token, { namespace }, (err, res) => { - if (err) { - debug(err); - if(err.response.badRequest) { - const { detail } = err.response.body; - if(detail) { - actionContext.dispatch('RECEIVE_TRIAL_LICENSE_BAD_REQUEST', detail); - } - } else { - actionContext.dispatch('RECEIVE_TRIAL_LICENSE_FACEPALM', err); - } - done(); - } else { - let license = find(res.body.licenses, (obj) => { - return obj.tier === 'Trial' || obj.alias === 'Trial'; - }); - license = merge({}, license, { namespace }); - actionContext.dispatch('RECEIVE_TRIAL_LICENSE', license); - done(); - } - }); - } else { - // user must be logged in; they aren't - const err = `You must be logged in to access your trial license`; - actionContext.dispatch('RECEIVE_TRIAL_LICENSE_BAD_REQUEST', err); - done(); - } -} diff --git a/app/scripts/actions/navigate/toOrg.js b/app/scripts/actions/navigate/toOrg.js deleted file mode 100644 index f1497b3af1..0000000000 --- a/app/scripts/actions/navigate/toOrg.js +++ /dev/null @@ -1,7 +0,0 @@ -'use strict'; -var debug = require('debug')('navigate::toOrg'); - -export default function updateOrgOwner({actionContext, payload, done, maybeData}){ - actionContext.dispatch('UPDATE_TO_ORG_OWNER', {owner: ''}); - done(); -} diff --git a/app/scripts/actions/navigate/user.js b/app/scripts/actions/navigate/user.js deleted file mode 100644 index 8dfe8eea64..0000000000 --- a/app/scripts/actions/navigate/user.js +++ /dev/null @@ -1,58 +0,0 @@ -'use strict'; -var debug = require('debug')('navigate::home'); -import async from 'async'; -import _ from 'lodash'; -import { - Repositories as Repos, - Users -} from 'hub-js-sdk'; - -export default function home({actionContext, payload, done, maybeData}){ - // This works without a jwt - var token = null; - - if (_.has(maybeData, 'token')) { - token = maybeData.token; - } - - //Get repos for user or org - var _getReposForUser = function(cb) { - actionContext.dispatch('DASHBOARD_REPOS_STORE_ATTEMPTING_GET_REPOS'); - Repos.getReposForUser(token, payload.params.user, function(err, res) { - if (err) { - cb(); - } else { - actionContext.dispatch('RECEIVE_PROFILE_REPOS', res.body); - cb(); - } - }, payload.location.query.page); - }; - - var _getUserByName = function(cb) { - Users.getUser(token, payload.params.user, function(err, res) { - if (err) { - if(res && res.notFound) { - actionContext.dispatch('USER_PROFILE_404'); - cb(err, null); - } else { - debug(err); - cb(); - } - } else { - actionContext.dispatch('RECEIVE_PROFILE_USER', res.body); - cb(); - } - }); - }; - - //Get user by name - async.parallel([ - _getReposForUser, - _getUserByName - ], function(err, results) { - if (err) { - debug(err); - } - return done(); - }); -} diff --git a/app/scripts/actions/navigate/userStars.js b/app/scripts/actions/navigate/userStars.js deleted file mode 100644 index 4e5e1d8f42..0000000000 --- a/app/scripts/actions/navigate/userStars.js +++ /dev/null @@ -1,57 +0,0 @@ -'use strict'; -var debug = require('debug')('navigate::userStars'); -import async from 'async'; -import _ from 'lodash'; -import { - Repositories as Repos, - Users -} from 'hub-js-sdk'; - -export default function userStars({actionContext, payload, done, maybeData}){ - // This works without a jwt - var token = null; - - if (_.has(maybeData, 'token')) { - token = maybeData.token; - } - - //Get repos for user or org - var _getStarredReposForUser = function(cb) { - Repos.getStarredReposForUser(token, payload.params.user, function(err, res) { - if (err) { - cb(); - } else { - actionContext.dispatch('RECEIVE_PROFILE_STARRED_REPOS', res.body); - cb(); - } - }, payload.location.query.page); - }; - - var _getUserByName = function(cb) { - Users.getUser(token, payload.params.user, function(err, res) { - if (err) { - if(res && res.notFound) { - actionContext.dispatch('USER_PROFILE_404'); - cb(err, null); - } else { - debug(err); - cb(); - } - } else { - actionContext.dispatch('RECEIVE_PROFILE_USER', res.body); - cb(); - } - }); - }; - - //Get user by name - async.parallel([ - _getStarredReposForUser, - _getUserByName - ], function(err, results) { - if (err) { - debug(err); - } - return done(); - }); -} diff --git a/app/scripts/actions/navigate/webhooks.js b/app/scripts/actions/navigate/webhooks.js deleted file mode 100644 index 930d0ce151..0000000000 --- a/app/scripts/actions/navigate/webhooks.js +++ /dev/null @@ -1,76 +0,0 @@ -'use strict'; - -import _ from 'lodash'; -import { parallel } from 'async'; -import { PENDING_DELETE } from 'common/enums/RepoStatus'; -import { - Repositories as Repos -} from 'hub-js-sdk'; -import getPipelines from '@dux/hub-sdk/webhooks/getPipelines'; - -var debug = require('debug')('action::webhooks'); - -const fetchRepo = ({ token, namespace, name }) => callback => { - Repos.getRepo(token, `${namespace}/${name}`, (err, { body }) => { - const { status } = body; - if (err || status === PENDING_DELETE) { - // We should handle other possible errors here (500, etc) - return callback('REPO_NOT_FOUND'); - } else { - return callback(null, body); - } - }); -}; - -const fetchPipelines = ({ token, namespace, name }) => callback => { - getPipelines(token, { - namespace, - name - }, (err, res) => { - if (err) { - return callback(); - } else { - return callback(null, res.body); - } - }); -}; - -export default function fetchWebhooksPageData({ - actionContext: { dispatch }, - payload: { params }, - done, - maybeData: { token, user } -}) { - - if (!token) { - dispatch('REPO_NOT_FOUND', null); - return done(); - } - - debug(params); - const { - user: namespace, - splat: name - } = params; - - parallel({ - repository: fetchRepo({ token, namespace, name }), - pipelines: fetchPipelines({ token, namespace, name }) - }, - (err, { repository, pipelines }) => { - if(err) { - debug('err', err); - /** - * If there's an error, 404 by default, but handle other - * errors in the future - */ - dispatch('REPO_NOT_FOUND', null); - done(); - } else { - debug('receive', repository, pipelines); - dispatch('RECEIVE_REPOSITORY', repository); - dispatch('RECEIVE_WEBHOOKS', pipelines); - done(); - } - }); -} diff --git a/app/scripts/actions/onAddCollaboratorChange.js b/app/scripts/actions/onAddCollaboratorChange.js deleted file mode 100644 index 8fb1d9f315..0000000000 --- a/app/scripts/actions/onAddCollaboratorChange.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -export default function onAddCollaboratorChange(actionContext, { collaborator }) { - actionContext.dispatch('ON_ADD_COLLAB_CHANGE', collaborator); -} diff --git a/app/scripts/actions/redux/tags.js b/app/scripts/actions/redux/tags.js deleted file mode 100644 index 3ae1df4988..0000000000 --- a/app/scripts/actions/redux/tags.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; - -import { Repositories as Repos } from 'hub-js-sdk'; -import { DELETE_REPO_TAG } from 'reduxConsts'; -const debug = require('debug')('hub:actions:redux:deleteRepoTag'); - -export const deleteRepoTag = ({ JWT, namespace, name, tagName }) => ({ - type: DELETE_REPO_TAG, - payload: { - namespace, - reponame: name, - tagName - }, - meta: { - sdk: { - call: Repos.deleteRepoTag, - args: [JWT, { namespace, name, tagName }], - callback: (err, res) => ({}), - statusKey: ['deleteRepoTag', tagName] - } - } -}); diff --git a/app/scripts/actions/regenTriggerToken.js b/app/scripts/actions/regenTriggerToken.js deleted file mode 100644 index d978f2fb2f..0000000000 --- a/app/scripts/actions/regenTriggerToken.js +++ /dev/null @@ -1,27 +0,0 @@ -'use strict'; -const debug = require('debug')('hub:actions:regenTriggerToken'); -import { - Autobuilds as AutoBuild - } from 'hub-js-sdk'; - -function getTriggerStatus(JWT, actionContext, namespace, name) { - AutoBuild.getTriggerStatus(JWT, namespace, name, function(err, res) { - if (err) { - debug('error', err); - } - if (res.ok) { - actionContext.dispatch('RECEIVE_TRIGGER_STATUS', res.body); - } - }); -} - -export default function regenTriggerToken(actionContext, {JWT, namespace, name}) { - AutoBuild.regenBuildTriggerToken(JWT, namespace, name, function(err, res) { - if (err) { - debug('error', err); - } - if (res.ok) { - getTriggerStatus(JWT, actionContext, namespace, name); - } - }); -} diff --git a/app/scripts/actions/removeTeam.js b/app/scripts/actions/removeTeam.js deleted file mode 100644 index 3c506007f7..0000000000 --- a/app/scripts/actions/removeTeam.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; - -var debug = require('debug')('hub:actions:removeTeam'); - -import { Orgs } from 'hub-js-sdk'; - -var removeTeam = function(actionContext, {jwt, orgname, teamname}) { - Orgs.deleteTeam(jwt, orgname, teamname, function(delErr, delRes) { - if (delErr) { - debug('error', delErr); - actionContext.dispatch('TEAM_ERROR', delErr); - } else if (delRes.ok) { - actionContext.dispatch('DELETE_DASHBOARD_TEAM_SUCCESS'); - actionContext.history.push(`/u/${orgname}/dashboard/teams/`); - Orgs.getTeams(jwt, orgname, function(err, res) { - if (err) { - debug('getTeams error', err); - } else { - actionContext.dispatch('RECEIVE_DASHBOARD_ORG_TEAMS', res.body); - } - }); - } - }); -}; - -module.exports = removeTeam; diff --git a/app/scripts/actions/removeTeamMember.js b/app/scripts/actions/removeTeamMember.js deleted file mode 100644 index 5d6b6b298a..0000000000 --- a/app/scripts/actions/removeTeamMember.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; - -var debug = require('debug')('hub:actions:removeTeamMember'); - -import { Orgs } from 'hub-js-sdk'; - -var removeTeamMember = function(actionContext, {jwt, orgname, teamname, membername}) { - Orgs.deleteMember(jwt, orgname, teamname, membername, function(delErr, delRes) { - if (delErr) { - debug('error', delErr); - actionContext.dispatch('TEAM_MEMBER_ERROR', delErr); - } else if (delRes.ok) { - Orgs.getMembers(jwt, orgname, teamname, function(err, res) { - if (err) { - debug('getMembers error', err); - } else { - actionContext.dispatch('RECEIVE_DASHBOARD_TEAM_MEMBERS', res.body); - } - }); - } - }); -}; - -module.exports = removeTeamMember; diff --git a/app/scripts/actions/removeTriggerLink.js b/app/scripts/actions/removeTriggerLink.js deleted file mode 100644 index 3a7d25f527..0000000000 --- a/app/scripts/actions/removeTriggerLink.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict'; -import _ from 'lodash'; -import { Autobuilds as AutoBuild } from 'hub-js-sdk'; -var debug = require('debug')('hub:actions:removeTriggerLink'); - -export default function(actionContext, { JWT, namespace, name, repo_id }) { - AutoBuild.deleteAutomatedBuildLink(JWT, namespace, name, repo_id, function(err, res) { - if (err) { - debug('error', err); - } else { - AutoBuild.getAutomatedBuildLinks(JWT, namespace, name, function(getErr, getRes){ - if (getErr) { - debug('getAutomatedBuildLinks error', err); - } else { - actionContext.dispatch('RECEIVE_AUTOBUILD_LINKS', getRes.body.results); - } - }); - } - }); -} diff --git a/app/scripts/actions/removeWebhookFromPipeline.js b/app/scripts/actions/removeWebhookFromPipeline.js deleted file mode 100644 index 6f77808a66..0000000000 --- a/app/scripts/actions/removeWebhookFromPipeline.js +++ /dev/null @@ -1,8 +0,0 @@ -'use strict'; - -export default function removeWebhookFromPipeline({ dispatch }, - params, - done) { - dispatch('ADD_WEBHOOK_REMOVE_HOOK'); - done(); -} diff --git a/app/scripts/actions/resendConfirmationEmail.js b/app/scripts/actions/resendConfirmationEmail.js deleted file mode 100644 index 336762c181..0000000000 --- a/app/scripts/actions/resendConfirmationEmail.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict'; -import { - Emails - } from 'hub-js-sdk'; -const debug = require('debug')('hub:actions:resendConfirmationEmail'); - -var resendConfirmationEmail = function(actionContext, {JWT, emailID}) { - actionContext.dispatch('RESEND_EMAIL_CONFIRMATION_ATTEMPT_START', emailID); - Emails.resendConfirmationEmail(JWT, emailID, function(err, res) { - if (err) { - debug('error', err); - actionContext.dispatch('RESEND_EMAIL_CONFIRMATION_FAILED', emailID); - } else { - actionContext.dispatch('RESEND_EMAIL_CONFIRMATION_SENT', emailID); - } - setTimeout(() => {actionContext.dispatch('RESEND_EMAIL_CONFIRMATION_CLEAR', emailID);}, 4000); - }); -}; - -module.exports = resendConfirmationEmail; diff --git a/app/scripts/actions/resetNotifications.js b/app/scripts/actions/resetNotifications.js deleted file mode 100644 index 0eef639999..0000000000 --- a/app/scripts/actions/resetNotifications.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict'; -import _ from 'lodash'; - -export default function(actionContext, slateArray) { - if (_.includes(slateArray, 'notifications')) { - actionContext.dispatch('RESET_EMAIL_NOTIFICATIONS_STORE'); - } - if (_.includes(slateArray, 'outbound')) { - actionContext.dispatch('RESET_OUTBOUND_EMAILS_STORE'); - } -} diff --git a/app/scripts/actions/resetPasswordSubmit.js b/app/scripts/actions/resetPasswordSubmit.js deleted file mode 100644 index d44247e627..0000000000 --- a/app/scripts/actions/resetPasswordSubmit.js +++ /dev/null @@ -1,21 +0,0 @@ -/* @flow */ -'use strict'; -import { - Users - } from 'hub-js-sdk'; -const debug = require('debug')('hub:actions:resetPasswordSubmit'); - -var resetPasswordSubmit = function(actionContext:{ dispatch : Function }, { uidb64, reset_token, password_1, password_2 }) { - Users.resetPassword(uidb64, password_1, password_2, reset_token, function(err, res) { - if (err) { - debug('error', err); - actionContext.dispatch('RESET_PASSWORD_ERROR', res.body); - } else if (res.ok) { - actionContext.dispatch('RESET_PASSWORD_SUCCESSFUL'); - actionContext.history.push('/account/password-reset-confirm/success/'); - actionContext.dispatch('CHANGE_PASS_CLEAR', {}); - } - }); -}; - -module.exports = resetPasswordSubmit; diff --git a/app/scripts/actions/resetWebhookForm.js b/app/scripts/actions/resetWebhookForm.js deleted file mode 100644 index 1de31e6100..0000000000 --- a/app/scripts/actions/resetWebhookForm.js +++ /dev/null @@ -1,8 +0,0 @@ -'use strict'; - -export default function resetWebhookForm({ dispatch }, - params, - done) { - dispatch('ADD_WEBHOOK_RESET'); - done(); -} diff --git a/app/scripts/actions/saveEmailNotifs.js b/app/scripts/actions/saveEmailNotifs.js deleted file mode 100644 index 3737bb7380..0000000000 --- a/app/scripts/actions/saveEmailNotifs.js +++ /dev/null @@ -1,51 +0,0 @@ -'use strict'; - -var debug = require('debug')('hub:actions:saveEmailNotifs'); -import async from 'async'; - -import { Notifications } from 'hub-js-sdk'; - -var saveEmailNotifs = function(actionContext, {jwt, notification}) { - actionContext.dispatch('START_SAVE_ACTION'); - var _saveNotificationSettings = function(cb) { - Notifications.setNotificationSubscription(jwt, notification, function(err, res) { - if (err) { - debug('error', err); - cb(err); - } else if (res.body && res.ok) { - return cb(null, res.body); - } - }); - }; - - var _getNotificationSettings = function(cb) { - //all good, do the next call to get the notifications - Notifications.getNotificationSubscriptions(jwt, function(err, res) { - if (err) { - debug('getNotificationSubscriptions error', err); - cb(err); - } else { - cb(null, res.body.results); - } - }); - }; - - async.series([ - function (callback) { - _saveNotificationSettings(callback); - }, - function (callback) { - _getNotificationSettings(callback); - } - ], function (err, results) { - if (err) { - debug('async.series callback error', err); - actionContext.dispatch('SAVE_NOTIFICATIONS_ERROR'); - } else if (results[1]) { - actionContext.dispatch('SAVE_NOTIFICATIONS_SUCCESS'); - actionContext.dispatch('RECEIVE_NOTIFICATIONS', results[1]); - } - }); -}; - -module.exports = saveEmailNotifs; diff --git a/app/scripts/actions/saveOrgProfile.js b/app/scripts/actions/saveOrgProfile.js deleted file mode 100644 index 37c6eed102..0000000000 --- a/app/scripts/actions/saveOrgProfile.js +++ /dev/null @@ -1,60 +0,0 @@ -'use strict'; - -var debug = require('debug')('ACTION::saveOrgProfile'); -import async from 'async'; -import { Orgs } from 'hub-js-sdk'; -//Organization Object -/* - { - id (string), - orgname (regex), - full_name (string), - location (string): Your Location on the world, - company (string): Your organization's name, - profile_url (url): Your place on the web, - gravatar_email (email): This address will define which picture of you is shown, - is_active (boolean): Designates whether user is active. Unselect this instead of deleting accounts., - date_joined (datetime), - gravatar_url (string) - } - */ -export default function(actionContext, {jwt, orgname, organization}) { - - var _updateOrg = function(cb) { - Orgs.updateOrg(jwt, orgname, organization, function(err, res) { - if (err) { - debug(err); - actionContext.dispatch('UPDATE_ORG_ERROR', err); - cb(err, {}); - } else { - if (res.ok) { - cb(null, res.body); - } - } - }); - }; - - //Get orgs for user - var _getUpdatedOrg = function(cb) { - Orgs.getOrg(jwt, orgname, function(err, res) { - if (err) { - debug(err); - cb(err, {}); - } else { - cb(null, res.body); - actionContext.dispatch('UPDATE_ORG_SUCCESS'); - } - }); - }; - - async.series([ - _updateOrg, - _getUpdatedOrg - ], function (err, results) { - if(err) { - debug(err); - } else { - actionContext.dispatch('RECEIVE_ORGANIZATION', results[1]); - } - }); -} diff --git a/app/scripts/actions/saveOutbound.js b/app/scripts/actions/saveOutbound.js deleted file mode 100644 index fbcb25adba..0000000000 --- a/app/scripts/actions/saveOutbound.js +++ /dev/null @@ -1,106 +0,0 @@ -'use strict'; - -import { parallel } from 'async'; -import isEmpty from 'lodash/lang/isEmpty'; -import { - Emails - } from 'hub-js-sdk'; -var debug = require('debug')('hub:actions:saveOutbound'); - -module.exports = function({ dispatch }, - { - JWT, - username, - weeklyDigest, - betaGroup - }) { - /*eslint-disable camelcase */ - var digestSubscribe = weeklyDigest.subscribed_emails; - var digestUnsubscribe = weeklyDigest.unsubscribed_emails; - var betaSubscribe = betaGroup.subscribed_emails; - var betaUnsubscribe = betaGroup.unsubscribed_emails; - /*eslint-enable camelcase */ - parallel({ - digestSubscribed: function (callback) { - Emails.subscribeEmails(JWT, username, { - /*eslint-disable camelcase */ - subscribed_emails: digestSubscribe, - mailing_list: 'DockerNewsMailingList' - /*eslint-enable camelcase*/ - }, function (err, res) { - if (err) { - callback(err); - } else { - callback(null, res); - } - }); - }, - betaSubscribed: function (callback) { - Emails.subscribeEmails(JWT, username, { - /*eslint-disable camelcase */ - subscribed_emails: betaSubscribe, - mailing_list: 'DockerBetaGroupMailingList' - /*eslint-enable camelcase */ - }, function (err, res) { - if (err) { - callback(err); - } else { - callback(null, res); - } - }); - }, - digestUnsubscribed: function (callback) { - if (!isEmpty(digestUnsubscribe)) { - Emails.unsubscribeEmails(JWT, username, { - /*eslint-disable camelcase */ - unsubscribed_emails: digestUnsubscribe, - mailing_list: 'DockerNewsMailingList' - /*eslint-enable camelcase */ - }, function (err, res) { - if (err) { - callback(err); - } else { - callback(null, res.body.unsubscribed); - } - }); - } else { - callback(null); - } - }, - betaUnsubscribed: function (callback) { - if (!isEmpty(betaUnsubscribe)) { - Emails.unsubscribeEmails(JWT, username, { - /*eslint-disable camelcase */ - unsubscribed_emails: betaUnsubscribe, - mailing_list: 'DockerBetaGroupMailingList' - /*eslint-enable camelcase */ - }, function (err, res) { - if (err) { - callback(err); - } else { - callback(null, res.body.unsubscribed); - } - }); - } else { - callback(null); - } - } - }, - function(err, res) { - if(err) { - debug(err); - dispatch('SAVE_OUTBOUND_ERROR'); - } else { - Emails.getEmailSubscriptions(JWT, username, function(error, response){ - if (error) { - return debug(error); - } - dispatch('RECEIVE_EMAIL_SUBSCRIPTIONS', { - weeklyDigest: response.body.DockerNewsMailingList, - betaGroup: response.body.DockerBetaGroupMailingList - }); - dispatch('SAVE_OUTBOUND_SUCCESS'); - }); - } - }); -}; diff --git a/app/scripts/actions/savePushAutoBuildSettings.js b/app/scripts/actions/savePushAutoBuildSettings.js deleted file mode 100644 index c20dee1a21..0000000000 --- a/app/scripts/actions/savePushAutoBuildSettings.js +++ /dev/null @@ -1,74 +0,0 @@ -'use strict'; -import { - Autobuilds - } from 'hub-js-sdk'; -import has from 'lodash/object/has'; -import merge from 'lodash/object/merge'; -import sortBy from 'lodash/collection/sortBy'; -import async from 'async'; -var debug = require('debug')('hub:actions:savePushAutoBuildSettings'); - -function saveTag({JWT, namespace, name}) { - return (tag, callback) => { - if (tag.isNew && !tag.toDelete) { // toDelete unecessary now as tags with isNew && toDelete SHOULD be removed - var ab = merge({}, tag, {repoName: name, namespace: namespace}); - Autobuilds.createAutomatedBuildTags(JWT, ab, function(err, res) { - if (err) { - debug(err); - tag.error = true; - callback(null, { tag, err }); - } else { - callback(null, res.body); - } - }); - } else if (tag.toDelete && !!tag.id) { - Autobuilds.deleteAutomatedBuildTags(JWT, namespace, name, tag.id, function(err, res){ - if (err) { - debug(err); - tag.error = true; - callback(null, { tag, err }); - } else { - callback(null, null); - } - }); - } else { - Autobuilds.updateAutomatedBuildTags(JWT, namespace, name, tag.id, tag, function(err, res){ - if (err) { - debug(err); - tag.error = true; - callback(null, { tag, err }); - } else { - callback(null, res.body); - } - }); - } - }; -} - -export default function(actionContext, {JWT, namespace, name, tags}, done) { - let encounteredError = false; - async.map(tags, saveTag({ JWT, namespace, name }), function(error, results) { - results.forEach( (resultTag) => { - if (has(resultTag, 'tag')) { - const { tag, err } = resultTag; - //We are keeping track of only `update` docker tag errors and at the moment we get them in `non_field_errors` - const nonFieldErrors = err.response.body.non_field_errors; - if (has(tag, 'error')) { - actionContext.dispatch('SAVE_BUILD_TAGS_ERROR', {name: tag.name, error: nonFieldErrors}); - encounteredError = true; - } - } - }); - if (!encounteredError) { - //Gets here only if there are no errors - actionContext.dispatch('SAVE_BUILD_TAGS_SUCCESS'); - const sorted = sortBy(results, 'id'); - actionContext.dispatch('UPDATE_AUTO_BUILD_SETTINGS', { - field: 'autoBuildStore', - key: 'build_tags', - value: sorted - }); - } - done(); - }); -} diff --git a/app/scripts/actions/saveSettingsData.js b/app/scripts/actions/saveSettingsData.js deleted file mode 100644 index dee5615660..0000000000 --- a/app/scripts/actions/saveSettingsData.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; -import { - Users, - JWT -} from 'hub-js-sdk'; -const debug = require('debug')('hub:actions:saveSettingsData'); - -var saveSettingsData = function(actionContext, payload) { - actionContext.dispatch('ACCOUNT_INFO_ATTEMPT_START'); - Users.updateUser(payload.JWT, payload.username, payload.updateData, function(err, res) { - if (err) { - debug(err); - actionContext.dispatch('ACCOUNT_INFO_BAD_REQUEST', err.response.body); - } else { - actionContext.dispatch('ACCOUNT_INFO_SUCCESS'); - setTimeout(() => {actionContext.dispatch('ACCOUNT_INFO_STATUS_CLEAR');}, 4000); - actionContext.dispatch('RECEIVE_USER', res.body); - } - }); -}; - -module.exports = saveSettingsData; diff --git a/app/scripts/actions/saveTeamProfile.js b/app/scripts/actions/saveTeamProfile.js deleted file mode 100644 index 4630603723..0000000000 --- a/app/scripts/actions/saveTeamProfile.js +++ /dev/null @@ -1,53 +0,0 @@ -'use strict'; - -var debug = require('debug')('hub:actions:saveTeamProfile'); -import async from 'async'; -import { Orgs } from 'hub-js-sdk'; -//Team Object -/* - { - id (string), - teamname (regex), - description (string) - } - */ -export default function(actionContext, {jwt, orgname, teamname, team}) { - - var _updateTeam = function(cb) { - Orgs.updateTeam(jwt, { orgname, teamname, team }, function(err, res) { - if (err) { - debug(err); - actionContext.dispatch('UPDATE_TEAM_ERROR', err); - cb(err, {}); - } else { - if (res.ok) { - actionContext.dispatch('UPDATE_TEAM_SUCCESS'); - cb(null, res.body); - } - } - }); - }; - - //Get Team for org - var _getUpdatedTeam = function(cb) { - Orgs.getTeam(jwt, orgname, team.name, function(err, res) { - if (err) { - debug(err); - cb(err, {}); - } else { - cb(null, res.body); - } - }); - }; - - async.series([ - _updateTeam, - _getUpdatedTeam - ], function (err, results) { - if(err) { - debug(err); - } else { - actionContext.dispatch('RECEIVE_ORG_TEAM', results[1]); - } - }); -} diff --git a/app/scripts/actions/selectOrganization.js b/app/scripts/actions/selectOrganization.js deleted file mode 100644 index ca2f46c77e..0000000000 --- a/app/scripts/actions/selectOrganization.js +++ /dev/null @@ -1,8 +0,0 @@ -/* @flow */ -'use strict'; - -//TODO: organization object needs to be documented in hub-js-sdk when available -module.exports = function(actionContext: {dispatch: Function}, - orgName: {orgName: string}) { - actionContext.dispatch('SELECT_ORGANIZATION', orgName); -}; diff --git a/app/scripts/actions/selectSourceRepoForAutobuild.js b/app/scripts/actions/selectSourceRepoForAutobuild.js deleted file mode 100644 index 46cd52b208..0000000000 --- a/app/scripts/actions/selectSourceRepoForAutobuild.js +++ /dev/null @@ -1,6 +0,0 @@ -'use strict'; - -//The source repository could be github, bitbucket or anything else in the future -export default function selectSourceRepoForAutobuild(actionContext, selectedSourceRepo) { - actionContext.dispatch('SELECT_SOURCE_REPO', selectedSourceRepo); -} diff --git a/app/scripts/actions/setNewPrimaryEmail.js b/app/scripts/actions/setNewPrimaryEmail.js deleted file mode 100644 index 4ba49a370f..0000000000 --- a/app/scripts/actions/setNewPrimaryEmail.js +++ /dev/null @@ -1,47 +0,0 @@ -'use strict'; - -import { sortByOrder } from 'lodash'; -import { series, each } from 'async'; -import { - Emails - } from 'hub-js-sdk'; -var debug = require('debug')('hub:actions:setNewPrimaryEmail'); - -function updateEmailSettings({ dispatch }, - { - JWT, username, emailId - }, - done) { - dispatch('START_SAVE_ACTION'); - series([ - function update(callback) { - debug('emailObject', emailId); - Emails.updateEmailByID(JWT, - emailId, - {primary: true}, - (err, res) => callback(null, res)); - } - ], - function afterUpdatingEmails(err, results) { - if (err) { - return debug(err); - } - Emails.getEmailsForUser(JWT, username, function(emailErr, res){ - if (emailErr) { - debug('emailErr', emailErr); - dispatch('FINISH_SAVE_ACTION'); - return done(); - } - var emails = res.body.results; - var sortedEmails = sortByOrder(emails, - ['primary', 'verified'], - [false, false]); - dispatch('RECEIVE_EMAILS', { - emails: sortedEmails - }); - dispatch('FINISH_SAVE_ACTION'); - }); - }); -} - -module.exports = updateEmailSettings; diff --git a/app/scripts/actions/shortDescriptionUpdateFormField.js b/app/scripts/actions/shortDescriptionUpdateFormField.js deleted file mode 100644 index 3acb1f78c6..0000000000 --- a/app/scripts/actions/shortDescriptionUpdateFormField.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict'; - -export default function({ dispatch }, - { fieldKey, fieldValue }, - done) { - dispatch('SHORT_DESCRIPTION_UPDATE_FIELD_WITH_VALUE', { - fieldKey, fieldValue - }); -} diff --git a/app/scripts/actions/signupUpdateFormField.js b/app/scripts/actions/signupUpdateFormField.js deleted file mode 100644 index 1b63a9a684..0000000000 --- a/app/scripts/actions/signupUpdateFormField.js +++ /dev/null @@ -1,7 +0,0 @@ -'use strict'; - -export default function(actionContext, { fieldKey, fieldValue }, done) { - actionContext.dispatch('SIGNUP_UPDATE_FIELD_WITH_VALUE', { - fieldKey, fieldValue - }); -} diff --git a/app/scripts/actions/signupValidations.js b/app/scripts/actions/signupValidations.js deleted file mode 100644 index 95f19464b1..0000000000 --- a/app/scripts/actions/signupValidations.js +++ /dev/null @@ -1,59 +0,0 @@ -'use strict'; - -var usernameValidation = function(actionContext, payload) { - var validationState; - var username = payload.unsafeUsername; - if (username.length > 3 && username.length <= 30 && username.match(/[a-z0-9\.\-_]+$/)) { - validationState = 'SUCCESS'; - } else if (username.length === 0) { - validationState = 'NOTHING'; - } else { - validationState = 'ERROR'; - } - actionContext.dispatch('VALIDATED_SIGNUP_USERNAME', { - username: username, - valState: validationState - }); -}; - -var passValidation = function(actionContext, payload) { - var validationState; - var password = payload.unsafePass; - if (password.length >= 5 && password.match(/[a-zA-Z]/) && password.match(/[0-9]/) && - password.match(/[\.-_!@#$%^&\*\(\)\[\]\{\}~:]/)) { - validationState = 'SUPERSUCCESS'; - } else if (password.length >= 5 && password.match(/[a-zA-Z]/) && password.match(/[0-9]/)) { - validationState = 'SUCCESS'; - } else if (password.length >= 5) { - validationState = 'WEAK'; - } else if (password.length === 0) { - validationState = 'NOTHING'; - } else if (password.length < 5) { - validationState = 'ERROR'; - } - actionContext.dispatch('VALIDATED_SIGNUP_PASSWORD', { - password: password, - valState: validationState - }); -}; -var emailValidation = function(actionContext, payload) { - var validationState; - var email = payload.unsafeEmail; - if (email.length > 3 && email.match(/.@./) && !email.match(/.\ ./)) { - validationState = 'SUCCESS'; - } else if (email.length === 0) { - validationState = 'NOTHING'; - } else { - validationState = 'ERROR'; - } - actionContext.dispatch('VALIDATED_SIGNUP_EMAIL', { - email: email, - valState: validationState - }); -}; - -module.exports = { - usernameValidation: usernameValidation, - passValidation: passValidation, - emailValidation: emailValidation -}; diff --git a/app/scripts/actions/toggleDeleteRepoNameConfirmBox.js b/app/scripts/actions/toggleDeleteRepoNameConfirmBox.js deleted file mode 100644 index d54621917b..0000000000 --- a/app/scripts/actions/toggleDeleteRepoNameConfirmBox.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -export default function(actionContext) { - actionContext.dispatch('TOGGLE_DELETE_REPO_NAME_CONFIRM_BOX'); -} diff --git a/app/scripts/actions/toggleLongDescriptionEdit.js b/app/scripts/actions/toggleLongDescriptionEdit.js deleted file mode 100644 index 0ebd88cdf3..0000000000 --- a/app/scripts/actions/toggleLongDescriptionEdit.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -export default function (actionContext, { isEditing }) { - actionContext.dispatch('TOGGLE_LONG_DESCRIPTION_EDIT', { isEditing }); -} diff --git a/app/scripts/actions/toggleShortDescriptionEdit.js b/app/scripts/actions/toggleShortDescriptionEdit.js deleted file mode 100644 index 438bcb1792..0000000000 --- a/app/scripts/actions/toggleShortDescriptionEdit.js +++ /dev/null @@ -1,6 +0,0 @@ -'use strict'; - -export default function (actionContext, { isEditing }) { - actionContext.dispatch('TOGGLE_SHORT_DESCRIPTION_EDIT', { isEditing }); -} - diff --git a/app/scripts/actions/toggleStarred.js b/app/scripts/actions/toggleStarred.js deleted file mode 100644 index 11a3c342f6..0000000000 --- a/app/scripts/actions/toggleStarred.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict'; - -import { - Repositories as Repos -} from 'hub-js-sdk'; -var debug = require('debug')('hub:actions:toggleStarred'); - -export default function(actionContext, {jwt, repoShortName, status}) { - if(status) { - Repos.starRepo(jwt, repoShortName, - function(err, res) { - if (err) { - debug(err); - } else if (res.ok) { - actionContext.dispatch('TOGGLE_STARRED_STATE', status); - } - } - ); - } else { - Repos.unstarRepo(jwt, repoShortName, - function(err, res) { - if (err) { - debug(err); - } else if (res.ok) { - actionContext.dispatch('TOGGLE_STARRED_STATE', status); - } - } - ); - } -} diff --git a/app/scripts/actions/toggleTriggerStatus.js b/app/scripts/actions/toggleTriggerStatus.js deleted file mode 100644 index b23abf2a91..0000000000 --- a/app/scripts/actions/toggleTriggerStatus.js +++ /dev/null @@ -1,27 +0,0 @@ -'use strict'; -const debug = require('debug')('hub:actions:toggleTriggerStatus'); -import { - Autobuilds as AutoBuild - } from 'hub-js-sdk'; - -function getTriggerStatus(JWT, actionContext, namespace, name) { - AutoBuild.getTriggerStatus(JWT, namespace, name, function(err, res) { - if (err) { - debug(err); - } - if (res.ok) { - actionContext.dispatch('RECEIVE_TRIGGER_STATUS', res.body); - } - }); -} - -export default function toggleTriggerStatus(actionContext, {JWT, namespace, name, active}) { - AutoBuild.toggleTriggerStatus(JWT, namespace, name, active, function(err, res) { - if (err) { - debug(err); - } - if (res.ok) { - getTriggerStatus(JWT, actionContext, namespace, name); - } - }); -} diff --git a/app/scripts/actions/toggleVisibility.js b/app/scripts/actions/toggleVisibility.js deleted file mode 100644 index 4b296d9d03..0000000000 --- a/app/scripts/actions/toggleVisibility.js +++ /dev/null @@ -1,23 +0,0 @@ -'use strict'; - -import { Users } from 'hub-js-sdk'; -var debug = require('debug')('hub:actions:toggleVisibility'); - -module.exports = function(actionContext, {JWT, username, visibility}) { - actionContext.dispatch('START TOGGLE REPO VISIBILITY'); - Users.updateDefaultVisibility(JWT, { username, visibility }, function(err, res){ - if (err) { - actionContext.dispatch('UPDATE_ORG_ERROR', err); - } else if (res.ok) { - Users.getUserSettings(JWT, username, function(getErr, getRes) { - if (getErr) { - debug(getErr); - } else if (getRes.ok) { - actionContext.dispatch('RECEIVE_PRIVATE_REPOSTATS', getRes.body); - let is_private = (getRes.body.default_repo_visibility === 'private'); - actionContext.dispatch('CREATE_REPO_UPDATE_FIELD_WITH_VALUE', {fieldKey: 'is_private', fieldValue: is_private}); - } - }); - } - }); -}; diff --git a/app/scripts/actions/toggleVisibilityRepoNameConfirmBox.js b/app/scripts/actions/toggleVisibilityRepoNameConfirmBox.js deleted file mode 100644 index 196a28bac2..0000000000 --- a/app/scripts/actions/toggleVisibilityRepoNameConfirmBox.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -export default function(actionContext) { - actionContext.dispatch('TOGGLE_VISIBILITY_REPO_NAME_CONFIRM_BOX'); -} diff --git a/app/scripts/actions/triggerBuild.js b/app/scripts/actions/triggerBuild.js deleted file mode 100644 index 06bd11ee9d..0000000000 --- a/app/scripts/actions/triggerBuild.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; - -import { Autobuilds } from 'hub-js-sdk'; -var debug = require('debug')('hub:actions:triggerBuild'); - -module.exports = function(actionContext, {JWT, name, namespace}) { - Autobuilds.triggerBuild(JWT, namespace, name, (err, res) => { - if (err) { - debug(err); - actionContext.dispatch('AB_TRIGGER_ERROR'); - } else { - actionContext.dispatch('AB_TRIGGER_SUCCESS'); - } - }); -}; diff --git a/app/scripts/actions/triggerBuildByTag.js b/app/scripts/actions/triggerBuildByTag.js deleted file mode 100644 index ba29f7bc59..0000000000 --- a/app/scripts/actions/triggerBuildByTag.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict'; - -import { Autobuilds } from 'hub-js-sdk'; -var debug = require('debug')('hub:actions:triggerBuildByTag'); - -module.exports = function(actionContext, {JWT, tag, triggerId}) { - let successStatus, errorStatus; - actionContext.dispatch('ATTEMPT_TRIGGER_BY_TAG', triggerId); - Autobuilds.triggerBuildByTag(JWT, tag, (err, res) => { - if (err) { - debug(err); - actionContext.dispatch('AB_TRIGGER_BY_TAG_ERROR', - { - error: 'Error triggering the build. Please check your source name.', - id: triggerId - }); - } else { - if (res.ok) { - switch(res.status) { - case 202: - successStatus = 'Successfully triggered a build.'; - break; - case 200: - successStatus = 'Attempted to trigger a build. Please check the build details page for more information.'; - //TODO: report this as error or success once it is clear what exactly this means - break; - default: - break; - } - actionContext.dispatch('AB_TRIGGER_BY_TAG_SUCCESS', {success: successStatus, id: triggerId}); - } - } - }); -}; diff --git a/app/scripts/actions/unlinkBitbucket.js b/app/scripts/actions/unlinkBitbucket.js deleted file mode 100644 index 55a3a9e911..0000000000 --- a/app/scripts/actions/unlinkBitbucket.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; - -import { Builds } from 'hub-js-sdk'; -const debug = require('debug')('hub:actions:unlinkBitbucket'); -import linkedAccountSettingsAction from './navigate/linkedAccountsSettings'; - -module.exports = function(actionContext, jwt) { - Builds.unlinkBitbucket(jwt, function(err, res) { - if (err) { - debug(err); - const { detail } = err.response.body; - if(detail) { - actionContext.dispatch('BITBUCKET_UNLINK_ERROR', detail); - } - } else if (res.ok) { - linkedAccountSettingsAction( - { - actionContext: actionContext, - payload: {}, - done: function() { debug('done unlinking bitbucket.'); }, - maybeData: {token: jwt} - } - ); - } - }); -}; diff --git a/app/scripts/actions/unlinkGithub.js b/app/scripts/actions/unlinkGithub.js deleted file mode 100644 index e5e7dbc021..0000000000 --- a/app/scripts/actions/unlinkGithub.js +++ /dev/null @@ -1,27 +0,0 @@ -'use strict'; - -import { Builds } from 'hub-js-sdk'; -const debug = require('debug')('hub:actions:unlinkGithub'); -import has from 'lodash/object/has'; -import linkedAccountSettingsAction from './navigate/linkedAccountsSettings'; - -module.exports = function(actionContext, jwt) { - Builds.unlinkGithub(jwt, function(err, res) { - if (err) { - debug(err); - const { detail } = err.response.body; - if(detail) { - actionContext.dispatch('GITHUB_UNLINK_ERROR', detail); - } - } else if (res.ok) { - linkedAccountSettingsAction( - { - actionContext: actionContext, - payload: {}, - done: function() { debug('done unlinking github account.'); }, - maybeData: {token: jwt} - } - ); - } - }); -}; diff --git a/app/scripts/actions/updateAccountInfoFormField.js b/app/scripts/actions/updateAccountInfoFormField.js deleted file mode 100644 index a70ccb1a5d..0000000000 --- a/app/scripts/actions/updateAccountInfoFormField.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -export default function(actionContext, { fieldKey, fieldValue}) { - actionContext.dispatch('ACCOUNT_INFO_UPDATE_FIELD_WITH_VALUE', { fieldKey, fieldValue }); -} diff --git a/app/scripts/actions/updateAddOrganizationFormField.js b/app/scripts/actions/updateAddOrganizationFormField.js deleted file mode 100644 index b11166861c..0000000000 --- a/app/scripts/actions/updateAddOrganizationFormField.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -export default function(actionContext, { fieldKey, fieldValue}) { - actionContext.dispatch('ADD_ORG_UPDATE_FIELD_WITH_VALUE', { fieldKey, fieldValue }); -} diff --git a/app/scripts/actions/updateAddRepositoryFormField.js b/app/scripts/actions/updateAddRepositoryFormField.js deleted file mode 100644 index 940c91053e..0000000000 --- a/app/scripts/actions/updateAddRepositoryFormField.js +++ /dev/null @@ -1,7 +0,0 @@ -'use strict'; - -export default function(actionContext, { fieldKey, fieldValue}) { - actionContext.dispatch('CREATE_REPO_UPDATE_FIELD_WITH_VALUE', { - fieldKey, fieldValue - }); -} diff --git a/app/scripts/actions/updateAutoBuildPushTriggerItem.js b/app/scripts/actions/updateAutoBuildPushTriggerItem.js deleted file mode 100644 index bd36a50333..0000000000 --- a/app/scripts/actions/updateAutoBuildPushTriggerItem.js +++ /dev/null @@ -1,12 +0,0 @@ -/* @flow */ -/*global VisibilityFormFieldPayload */ -'use strict'; - -var debug = require('debug')('hub:actions:updateAutoBuildPushTriggerItem'); -export default function(actionContext, { isNew, index, fieldkey, value}) { - if (isNew) { - actionContext.dispatch('UPDATE_AUTOBUILD_NEW_TAG_ITEM', {index, fieldkey, value}); - } else { - actionContext.dispatch('UPDATE_AUTOBUILD_PUSH_TRIGGER_ITEM', {index, fieldkey, value}); - } -} diff --git a/app/scripts/actions/updateAutoBuildSettings.js b/app/scripts/actions/updateAutoBuildSettings.js deleted file mode 100644 index 08fc59e2e9..0000000000 --- a/app/scripts/actions/updateAutoBuildSettings.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict'; - -import { Autobuilds } from 'hub-js-sdk'; -var debug = require('debug')('hub:actions:updateAutoBuildSettings'); - -module.exports = function(actionContext, {JWT, namespace, name, data}) { - Autobuilds.updateAutomatedBuildSettings(JWT, namespace, name, data, function(err, res){ - if (err) { - debug(res.body); - } else if (res.ok) { - Autobuilds.getAutomatedBuildSettings(JWT, namespace, name, function(getErr, getRes) { - if (getErr) { - debug(getErr); - } else if (getRes.ok) { - actionContext.dispatch('RECEIVE_AUTOBUILD_SETTINGS', getRes.body); - } - }); - } - }); -}; diff --git a/app/scripts/actions/updateAutoBuildSettingsStore.js b/app/scripts/actions/updateAutoBuildSettingsStore.js deleted file mode 100644 index 82fc8de4c3..0000000000 --- a/app/scripts/actions/updateAutoBuildSettingsStore.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -export default function(actionContext, { field, key, value}) { - actionContext.dispatch('UPDATE_AUTO_BUILD_SETTINGS', {field, key, value}); -} diff --git a/app/scripts/actions/updateAutobuildFormField.js b/app/scripts/actions/updateAutobuildFormField.js deleted file mode 100644 index 6e06bc9486..0000000000 --- a/app/scripts/actions/updateAutobuildFormField.js +++ /dev/null @@ -1,7 +0,0 @@ -'use strict'; - -export default function(actionContext, { fieldKey, fieldValue}) { - actionContext.dispatch('AUTOBUILD_FORM_UPDATE_FIELD_WITH_VALUE', { - fieldKey, fieldValue - }); -} diff --git a/app/scripts/actions/updateBillingInfoFormField.js b/app/scripts/actions/updateBillingInfoFormField.js deleted file mode 100644 index b386a3de83..0000000000 --- a/app/scripts/actions/updateBillingInfoFormField.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; - -export default function(actionContext, { field, fieldKey, fieldValue}) { - if (field === 'card' && fieldKey === 'number') { - var type = window.recurly.validate.cardType(fieldValue.toString()); - actionContext.dispatch('BILLING_INFO_UPDATE_FIELD_WITH_VALUE', { - field: 'card', - fieldKey: 'type', - fieldValue: type - }); - } - actionContext.dispatch('BILLING_INFO_UPDATE_FIELD_WITH_VALUE', { - field, fieldKey, fieldValue - }); -} diff --git a/app/scripts/actions/updateBillingInformation.js b/app/scripts/actions/updateBillingInformation.js deleted file mode 100644 index 669ae950bb..0000000000 --- a/app/scripts/actions/updateBillingInformation.js +++ /dev/null @@ -1,87 +0,0 @@ -'use strict'; -/*global UpdateBillingInfoPayload */ -import { Billing } from 'hub-js-sdk'; -import _ from 'lodash'; -import async from 'async'; -var debug = require('debug')('hub:actions:updateBillingInformation'); - -function updateBillingInformation(actionContext, {JWT, user, billingInfo, accountInfo, card}, done) { - actionContext.dispatch('BILLING_SUBMIT_START'); - var recurlyData = _.merge({}, billingInfo, card); - let isOrg = false; - let username = ''; - if (_.has(user, 'username')) { - username = user.username; - } else if (_.has(user, 'orgname')) { - username = user.orgname; - isOrg = true; - } - const account = _.merge({}, accountInfo, {user: username}); - - try { - /** - * This will only run where window is defined. ie: the browser - * It throws an exception in node - */ - window.recurly.configure(process.env.RECURLY_PUBLIC_KEY); - } catch(e) { - debug('error', e); - } - window.recurly.token(recurlyData, function(recurlyErr, token) { - if (recurlyErr) { - // SHOULD ONLY GET HERE IF RECURLY DECLINES THEIR INFO - debug('recurly error', recurlyErr); - actionContext.dispatch('GET_RECURLY_ERROR', recurlyErr); - done(); - } else { - async.series([ - function(callback){ - Billing.updateBillingAccount(JWT, username, account, function(accountErr, accountRes){ - if (accountErr) { - let message = 'There was an error updating your contact information. Please check your information and try again.'; - if (_.has(accountRes.body, 'detail') && _.isString(accountRes.body.detail)) { - message = accountRes.body.detail; - } - actionContext.dispatch('BILLING_SUBMIT_ERROR', message); - callback(accountErr, accountRes); - } else if (accountRes.ok) { - callback(null, accountRes.body); - } - }); - }, - function(callback) { - let updatedInfo = {username: username, payment_token: token.id}; - Billing.updateBillingInfo(JWT, username, updatedInfo, function(billErr, billRes) { - if (billErr) { - debug('updateBillingInfo error', billErr); - let message = 'There was an error submitting your billing information. Please check your information and try again.'; - if (_.has(billRes.body, 'detail') && _.isString(billRes.body.detail)) { - message = billRes.body.detail; - } - actionContext.dispatch('BILLING_SUBMIT_ERROR', message); - callback(billErr, billRes); - } else if (billRes.ok) { - callback(null, billRes.body); - } - }); - } - ], - function(err, res) { - if (err) { - done(); - } else { - if (isOrg) { - actionContext.history.push(`/u/${username}/dashboard/billing/`); - } else { - actionContext.history.push('/account/billing-plans/'); - } - actionContext.dispatch('RECEIVE_BILLING_INFO', {billingInfo: res[1], accountInfo: res[0]}); - actionContext.dispatch('BILLING_SUBMIT_SUCCESS'); - done(); - } - }); - } - }); -} - -module.exports = updateBillingInformation; diff --git a/app/scripts/actions/updateChangePassStore.js b/app/scripts/actions/updateChangePassStore.js deleted file mode 100644 index cdea3e35a4..0000000000 --- a/app/scripts/actions/updateChangePassStore.js +++ /dev/null @@ -1,7 +0,0 @@ -'use strict'; - -var updateStore = function(actionContext, payload) { - actionContext.dispatch('CHANGE_PASS_UPDATE', payload); -}; - -module.exports = updateStore; diff --git a/app/scripts/actions/updateCloudBillingSubscription.js b/app/scripts/actions/updateCloudBillingSubscription.js deleted file mode 100644 index 3341a87f51..0000000000 --- a/app/scripts/actions/updateCloudBillingSubscription.js +++ /dev/null @@ -1,35 +0,0 @@ -'use strict'; -/** - * CLONE OF updateSubscriptionPlanOrPackage.js - * with Different dispatches - */ -import { Billing } from 'hub-js-sdk'; -import has from 'lodash/object/has'; -var debug = require('debug')('hub:actions:updateCloudBillingSubscription'); - -function updateBillingSubscriptions(actionContext, {JWT, username, subscription_uuid, package_code, coupon_code, isOrg}, done) { - actionContext.dispatch('ENTERPRISE_PAID_ATTEMPT_START'); - var data = { - package: package_code, - username, - coupon_code - }; - Billing.updateBillingSubscriptions(JWT, subscription_uuid, username, data, function(err, res) { - if (err) { - debug(err); - // If fails - There's nothing else we can do. Facepalm - actionContext.dispatch('ENTERPRISE_PAID_BAD_REQUEST', res.body.detail); - done(); - } else if (res.ok) { - actionContext.dispatch('ENTERPRISE_PAID_SUCCESS'); - if (isOrg) { - actionContext.history.push(`/u/${username}/dashboard/billing/`); - } else { - actionContext.history.push('/account/billing-plans/'); - } - done(); - } - }); -} - -module.exports = updateBillingSubscriptions; diff --git a/app/scripts/actions/updateEnterpriseTrialFormField.js b/app/scripts/actions/updateEnterpriseTrialFormField.js deleted file mode 100644 index 481545ac79..0000000000 --- a/app/scripts/actions/updateEnterpriseTrialFormField.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -export default function(actionContext, {fieldKey, fieldValue}) { - actionContext.dispatch('ENTERPRISE_TRIAL_UPDATE_FIELD_WITH_VALUE', { fieldKey, fieldValue }); -} diff --git a/app/scripts/actions/updateNotifCheckbox.js b/app/scripts/actions/updateNotifCheckbox.js deleted file mode 100644 index 26697d0aa2..0000000000 --- a/app/scripts/actions/updateNotifCheckbox.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -export default function(actionContext, cboxType) { - actionContext.dispatch('NOTIF_CHECKBOX_CLICK', cboxType); -} diff --git a/app/scripts/actions/updateOutbound.js b/app/scripts/actions/updateOutbound.js deleted file mode 100644 index cba8bae610..0000000000 --- a/app/scripts/actions/updateOutbound.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -export default function(actionContext, newList) { - actionContext.dispatch('UPDATE_OUTBOUND', newList); -} diff --git a/app/scripts/actions/updateRepoSettingsVisibilityField.js b/app/scripts/actions/updateRepoSettingsVisibilityField.js deleted file mode 100644 index 38259ca559..0000000000 --- a/app/scripts/actions/updateRepoSettingsVisibilityField.js +++ /dev/null @@ -1,56 +0,0 @@ -'use strict'; - -import async from 'async'; -var debug = require('debug')('hub:actions:updateRepoSettingsVisibilityField'); -import { Repositories as Repos, Users } from 'hub-js-sdk'; - -function updateRepoVisibility(actionContext, { jwt, isPrivate, repoShortName }) { - return (cb) => { - Repos.updateRepoVisibility(jwt, { isPrivate, repoShortName }, (err, res) => { - if (err) { - const { badRequest, body } = err.response; - if(badRequest) { - debug(err); - actionContext.dispatch('VISIBILITY_BAD_REQUEST', body); - cb(err); - } else if (res && res.body.error) { - actionContext.dispatch('VISIBILITY_ERROR', res.body); - cb(err); - } else { - actionContext.dispatch('VISIBILITY_ERROR'); - cb(err); - } - } else { - actionContext.dispatch('TOGGLE_VISIBILITY_SUCCESS', isPrivate); - cb(null, res.body); - } - }); - }; -} - -function getPrivateRepoStats(actionContext, { jwt, repoShortName }) { - return (cb) => { - const namespace = repoShortName.split('/')[0]; - Users.getUserSettings(jwt, namespace, function (err, res) { - if (err) { - cb(); - } else { - actionContext.dispatch('RECEIVE_PRIVATE_REPOSTATS', res.body); - cb(); - } - }); - }; -} - - -export default function(actionContext, { jwt, isPrivate, repoShortName }, done) { - actionContext.dispatch('TOGGLE_VISIBILITY_ATTEMPT_START'); - async.series([ - updateRepoVisibility(actionContext, { jwt, isPrivate, repoShortName }), - getPrivateRepoStats(actionContext, {jwt, repoShortName }) - ], function(err, results) { - if (err) { - debug(err); - } - }); -} diff --git a/app/scripts/actions/updateStripeBilling.js b/app/scripts/actions/updateStripeBilling.js deleted file mode 100644 index 826f4eb6e5..0000000000 --- a/app/scripts/actions/updateStripeBilling.js +++ /dev/null @@ -1,292 +0,0 @@ -'use strict'; -/*global UpdateBillingInfoPayload */ -const request = require('superagent'); -import { Billing } from 'hub-js-sdk'; -import has from 'lodash/object/has'; -import merge from 'lodash/object/merge'; -import map from 'lodash/collection/map'; -import find from 'lodash/collection/find'; -import isString from 'lodash/lang/isString'; -import async from 'async'; -var debug = require('debug')('hub:actions:updateBillingInformation'); - -import _encodeForm from '../components/utils/encodeForm.js'; -import { - ACCOUNT, - BILLING, - BILLFORWARD_ACCOUNT_ID, - STRIPE_URL, - STRIPE_STAGE_TOKEN, - STRIPE_PROD_TOKEN, - BF_STAGE_URL, - BF_PROD_URL, - BF_STAGE_TOKEN, - BF_PROD_TOKEN, - v4BillingProfile -} from 'stores/common/Constants.js'; - -const handleResponse = ({ callback, dispatch, type }) => (err, res) => { - if (err) { - let message; - if (type === ACCOUNT) { - message = 'There was an error updating your account profile information. Please check your information and try again.'; - } else if (type === BILLING) { - message = 'There was an error updating your billing information. Please check your information and try again.'; - } - if (res && res.body) { - message = isString(res.body.detail) ? res.body.detail : res.body.message; - } - dispatch('BILLING_SUBMIT_ERROR', message); - callback(err, res); - } else if (res.ok) { - if (type === ACCOUNT) { - dispatch('BILLING_ACCOUNT_EXISTS'); - } else if (type === BILLING) { - dispatch('BILLING_INFO_EXISTS'); - } - const billforward_id = res.header[BILLFORWARD_ACCOUNT_ID]; - callback(null, { ...res.body, billforward_id }); - } -}; - -/* - NOTE: Stripe's api only accepts x-www-form-urlencoded data - NOTE: 'billforwardCreatePayment' is chained to this function and requires - `billforward-id`. The `billforward-id` is being passed through to the - create payment function via the META here. -*/ -function _createCardToken({ - cvc, - exp_month, - exp_year, - name_first, - name_last, - number -}, cb) { - const stripeToken = process.env.ENV === 'production' ? - STRIPE_PROD_TOKEN : STRIPE_STAGE_TOKEN; - const card = { - name: `${name_first} ${name_last}`, - cvc, - number, - exp_month, - exp_year - }; - const encoded = _encodeForm({ card }); - request.post(STRIPE_URL) - .accept('application/json') - .type('application/x-www-form-urlencoded') - .set('Authorization', 'Bearer ' + stripeToken) - .send(encoded) - .end(cb); -} - -/* - NOTE: This is the call to billforward that actually adds a payment method - to a user's billing profile. - This call requires a billforward-id (accountID) which is DIFFERENT than the - docker_id - Hence why 'billingCreatePaymentMethod' is NOT being wrapped by - the getAccountFromNamespace decorator. -*/ -function _billforwardAddPaymentMethod({ - '@type': type, - accountID, - cardID, - defaultPaymentMethod, - gateway, - stripeToken -}, cb) { - const billforwardUrl = process.env.ENV === 'production' ? - BF_PROD_URL : BF_STAGE_URL; - const billforwardToken = process.env.ENV === 'production' ? - BF_PROD_TOKEN : BF_STAGE_TOKEN; - - request.post(billforwardUrl) - .accept('application/json') - .type('application/json') - .set('Authorization', 'Bearer ' + billforwardToken) - .send({ - '@type': type, - accountID, - cardID, - defaultPaymentMethod, - gateway, - stripeToken - }) - .end(cb); -} - -//-------------------------------------------------------------------------- -// CREATE A BILLING PAYMENT METHOD ON BILLFORWAD WITH STRIPE -// DUPLICATED FROM ./createStripeSubscription.js -//-------------------------------------------------------------------------- -function billingCreatePaymentMethod(dispatch, { - billforwardId, - cvc, - exp_month, - exp_year, - name_first, - name_last, - number -}, cb) { - const cardData = { - cvc, - exp_month, - exp_year, - name_first, - name_last, - number - }; - /* - NOTE: - Creating a payment method requires 2 parts - 1 - Generating a token from Stripe's api - 2 - Sending generated token to Billforward's api to attach payment method to - a relevant billing profile. - */ - _createCardToken(cardData, (stripeErr, stripeRes) => { - if (!stripeRes.ok) { - let message = 'There was an error submitting your card information. Please check your information and try again.'; - if (stripeRes.error && stripeRes.error.message) { - message = stripeRes.error.message; - } - dispatch('BILLING_SUBMIT_ERROR', message); - cb(message); - } else { - const tokenObject = stripeRes && stripeRes.body; - const stripeToken = tokenObject.id; - const cardID = tokenObject.card.id; - const accountID = billforwardId; - const bfData = { - '@type': 'StripeAuthCaptureRequest', - accountID, - cardID, - defaultPaymentMethod: true, - gateway: 'Stripe', - stripeToken - }; - _billforwardAddPaymentMethod(bfData, handleResponse({callback: cb, dispatch, type: BILLING})); - } - }); -} -//-------------------------------------------------------------------------- -// SAVE ADDRESS INFORMATION IN BILLFORWARD -//-------------------------------------------------------------------------- -const updateV4BillingProfile = ({ JWT, profileData, docker_id }, cb) => { - const v4BillingAPI = v4BillingProfile(docker_id); - request - .patch(v4BillingAPI) - .accept('application/json') - .type('application/json') - .set('Authorization', 'Bearer ' + JWT) - .send(profileData) - .end(cb); -}; - -//-------------------------------------------------------------------------- -// UPDATE STRIPE BILLING INFORMATION -// NOTE: This will just add a payment method - creating multiple cards -//-------------------------------------------------------------------------- -function updateBillingInformation(actionContext, { - JWT, - user, - billingInfo, - accountInfo, - card, - billforwardId -}, done) { - actionContext.dispatch('BILLING_SUBMIT_START'); - let isOrg = false; - let username = ''; - if (has(user, 'username')) { - username = user.username; - } else if (has(user, 'orgname')) { - username = user.orgname; - isOrg = true; - } - const { - email, - first_name, - last_name, - company_name - } = accountInfo; - const { - address1, - address2, - country, - state, - zip, - city, - first_name: billing_first, - last_name: billing_last - } = billingInfo; - const { - number, - cvv, - month, - year - } = card; - - async.series([ - function(callback){ - const account = merge({}, accountInfo, {user: username}); - Billing.updateBillingAccount(JWT, username, account, handleResponse({callback, dispatch: actionContext.dispatch, type: ACCOUNT})); - }, - function(callback) { - /* - NOTE: - THIS WILL CREATE A NEW PAYMENT METHOD ON EVERY CALL - - In billforward this could potentially save multiple versions of the same card - - Solution would be to check whether the card is the same and decide to create or not - */ - billingCreatePaymentMethod(actionContext.dispatch, { - billforwardId, - cvc: cvv, - exp_month: month, - exp_year: year, - name_first: billing_first, - name_last: billing_last, - number - }, callback); - }, - function(callback) { - const profileData = { - first_name, - last_name, - addresses: [ - { - address_line_1: address1, - address_line_2: address2, - city, - province: state, - country, - post_code: zip, - primary_address: true - } - ] - }; - updateV4BillingProfile({ - JWT, - profileData, - docker_id: user.id - }, handleResponse({callback, dispatch: actionContext.dispatch, type: ACCOUNT})); - } - ], - function(err, res) { - if (err) { - done(); - } else { - if (isOrg) { - actionContext.history.push(`/u/${username}/dashboard/billing/`); - } else { - actionContext.history.push('/account/billing-plans/'); - } - actionContext.dispatch('BILLING_SUBMIT_SUCCESS'); - done(); - } - }); - - -} - -module.exports = updateBillingInformation; diff --git a/app/scripts/actions/updateSubscriptionPlanOrPackage.js b/app/scripts/actions/updateSubscriptionPlanOrPackage.js deleted file mode 100644 index b4ea288715..0000000000 --- a/app/scripts/actions/updateSubscriptionPlanOrPackage.js +++ /dev/null @@ -1,66 +0,0 @@ -'use strict'; -/*global UpdateBillingInfoPayload */ -import { Billing } from 'hub-js-sdk'; -import _ from 'lodash'; -const CLOUD_METERED = 'cloud_metered'; -var debug = require('debug')('hub:actions:updateSubscriptionPlanOrPackage'); - -function updateBillingSubscriptions(actionContext, { - coupon_code, - JWT, - package_code, - plan_code, - username, - subscription_uuid, - add_ons - }, done) { - actionContext.dispatch('UPDATE_PLAN_START', plan_code); - var data = { - username, - coupon_code, - add_ons - }; - - // we are either updating a plan or a package - if (plan_code) { - data.plan = plan_code; - } - if (package_code) { - data.package = package_code; - } - - // Explicitly remove all add ons (such as nautilus) when downgrading to - // a free account - if (plan_code === CLOUD_METERED) { - data.add_ons = []; - } - - if (!plan_code || plan_code === CLOUD_METERED) { - actionContext.dispatch('UNSUBSCRIBE_PLAN'); - } else if (!package_code) { - actionContext.dispatch('UNSUBSCRIBE_PACKAGE'); - } - Billing.updateBillingSubscriptions(JWT, subscription_uuid, username, data, function(err, res) { - if (err) { - debug(err); - const detail = err.response && err.response.body && err.response.body.detail; - const error = detail || 'Could not reach server.'; - actionContext.dispatch('UPDATE_PLAN_ERROR', error); - done(); - } else if (res.ok) { - Billing.getBillingSubscriptions(JWT, username, function(getErr, getRes) { - if (getErr) { - debug(getErr); - } else if (getRes.ok) { - let subscriptions = getRes.body; - let subscription = _.head(subscriptions); - // This will update your subscription in the store - while leaving the billing information the same - actionContext.dispatch('RECEIVE_BILLING_SUBSCRIPTION', {currentPlan: subscription}); - } - done(); - }); - } - }); -} - -module.exports = updateBillingSubscriptions; diff --git a/app/scripts/actions/updateToOrgOwner.js b/app/scripts/actions/updateToOrgOwner.js deleted file mode 100644 index 9ea02666c0..0000000000 --- a/app/scripts/actions/updateToOrgOwner.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -export default function(actionContext, payload) { - actionContext.dispatch('UPDATE_TO_ORG_OWNER', payload); -} diff --git a/app/scripts/actions/validateCouponCode.js b/app/scripts/actions/validateCouponCode.js deleted file mode 100644 index 0c3a8e57bc..0000000000 --- a/app/scripts/actions/validateCouponCode.js +++ /dev/null @@ -1,45 +0,0 @@ -'use strict'; -var debug = require('debug')('hub:actions:validateCouponCode'); - -module.exports = (actionContext, {coupon_code, plan}) => { - if (coupon_code) { - try { - /** - * This will only run where window is defined. ie: the browser - * It throws an exception in node - */ - window.recurly.configure(process.env.RECURLY_PUBLIC_KEY); - /* eslint-disable new-cap */ - var pricing = window.recurly.Pricing(); - /* eslint-enable new-cap*/ - pricing - .plan(plan, {quantity: 1}) - .coupon(coupon_code) - .catch(function(err) { - debug('ERROR', err); - actionContext.dispatch('BILLING_ERRORS', {fieldErrors: {coupon_code: true}}); - }) - .done(function(price) { - var discount = price.now.discount; - if (discount % 1 === 0) { - // remove the trailing decimals if its a whole number - discount = Math.round(discount); - } - actionContext.dispatch('UPDATE_COUPON_VALUE', discount); - if (discount <= 0) { - actionContext.dispatch('BILLING_ERRORS', {fieldErrors: {coupon_code: true}}); - } else { - actionContext.dispatch('BILLING_ERRORS', {fieldErrors: {coupon_code: false}}); - } - }); - } catch(e) { - debug('error', e); - actionContext.dispatch('BILLING_ERRORS', {fieldErrors: {coupon_code: true}}); - } - actionContext.dispatch('BILLING_INFO_UPDATE_FIELD_WITH_VALUE', {field: 'card', fieldKey: 'coupon_code', fieldValue: coupon_code}); - } else { - actionContext.dispatch('BILLING_ERRORS', {fieldErrors: {coupon_code: false}}); - actionContext.dispatch('BILLING_INFO_UPDATE_FIELD_WITH_VALUE', {field: 'card', fieldKey: 'coupon_code', fieldValue: ''}); - actionContext.dispatch('UPDATE_COUPON_VALUE', 0); - } -}; diff --git a/app/scripts/app.js b/app/scripts/app.js deleted file mode 100644 index 5aaec97293..0000000000 --- a/app/scripts/app.js +++ /dev/null @@ -1,103 +0,0 @@ -'use strict'; -const debug = require('debug')('hub:app'); -const Fluxible = require('fluxible'); - -let app = new Fluxible({ - component: require('./components/Routes.jsx'), - stores: [ - require('./stores/AccountInfoFormStore'), - require('./stores/AccountSettingsLicensesStore'), - require('./stores/AddOrganizationStore'), - require('./stores/AddTrialLicenseStore'), - require('./stores/AddWebhookFormStore'), - require('./stores/ApplicationStore'), - require('./stores/AutobuildConfigStore'), - require('./stores/AutoBuildSettingsStore'), - require('./stores/AutobuildSourceRepositoriesStore'), - require('./stores/AutobuildStore'), - require('./stores/AutobuildTagsStore'), - require('./stores/AutobuildTriggerByTagStore'), - require('./stores/BillingInfoFormStore'), - require('./stores/BillingPlansStore'), - require('./stores/BitbucketLinkStore'), - require('./stores/ChangePasswordStore'), - require('./stores/CloudCouponStore'), - require('./stores/CloudBillingStore'), - require('./stores/ConvertToOrgStore'), - require('./stores/CreateRepositoryFormStore'), - require('./stores/DashboardContribsStore'), - require('./stores/DashboardMembersStore'), - require('./stores/DashboardNamespacesStore'), - require('./stores/DashboardReposStore'), - require('./stores/DashboardStarsStore'), - require('./stores/DashboardStore'), - require('./stores/DashboardTeamsStore'), - require('./stores/DeletePipelineStore'), - require('./stores/DeleteRepoFormStore'), - require('./stores/EmailNotifStore'), - require('./stores/EmailsStore'), - require('./stores/EnterprisePaidFormStore'), - require('./stores/EnterprisePartnerTrackingStore'), - require('./stores/EnterpriseTrialFormStore'), - require('./stores/EnterpriseTrialSuccessStore'), - require('./stores/GithubLinkStore'), - require('./stores/JWTStore'), - require('./stores/LoginStore'), - require('./stores/NotifyStore'), - require('./stores/OrgTeamStore'), - require('./stores/OrganizationStore'), - require('./stores/OutboundCommunicationStore'), - require('./stores/PipelineHistoryStore'), - require('./stores/PlansStore'), - require('./stores/PrivateRepoUsageStore'), - require('./stores/RepoDetailsBuildLogs'), - require('./stores/RepoDetailsBuildsStore'), - require('./stores/RepoDetailsDockerfileStore'), - require('./stores/RepoDetailsLongDescriptionFormStore'), - require('./stores/RepoDetailsShortDescriptionFormStore'), - require('./stores/RepoDetailsVisibilityFormStore'), - require('./stores/RepoSettingsCollaborators'), - require('./stores/RepositoryCommentsStore'), - require('./stores/RepositoryPageStore'), - require('./stores/SearchStore'), - require('./stores/SignupStore'), - require('./stores/TriggerBuildStore'), - require('./stores/UserProfileReposStore'), - require('./stores/UserProfileStore'), - require('./stores/UserProfileStarsStore'), - require('./stores/UserStore'), - require('./stores/WebhooksSettingsStore') - ] -}); - -/** - * Add a plugin which adds the global redux store as .reduxStore to all flux - * actions. - * - * This allows us to call actionContext.reduxStore.dispatch() to dispatch - * actions from fluxible actions - */ -app.plug({ - name: 'ReduxActionIntegration', - plugContext(options, context) { - // Options should be passed reduxStore from the options passed into - // createContext - - return { - // Each action's context should also have the redux store that's defined - // within the app context. - plugActionContext(actionContext) { - // NOTE: Server-side rendering passes this in as options. - // Client-side rendering passes this in as context. - // Fluxible has no way to specify options within rehydration. - // We can only affect context. - - // This is defined in server.js within `server.use` for server-side - // rendering and within `app.rehydrate` in client.js - actionContext.reduxStore = options.reduxStore || context.reduxStore; - } - }; - } -}); - -export default app; diff --git a/app/scripts/bootstrapCreateElement.js b/app/scripts/bootstrapCreateElement.js deleted file mode 100644 index 1f9ccce538..0000000000 --- a/app/scripts/bootstrapCreateElement.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict'; - -import React from 'react'; -import provideContext from 'fluxible-addons-react/provideContext'; -const debug = require('debug')('hub:bootstrapCreateElement'); -/** - * We create a react element for the Router using this function, passing it to - * the `createElement` (func) property in . This will enable us to - * provide context for the Fluxible app and adds some context functions like - * `executeAction` and `getStore` to all components in our Routes. - * - * context is a Fluxible Context. - */ -export default (context) => { - return (component, props) => { - debug('setting context'); - props.context = context.getComponentContext(); - props.JWT = props.JWT || (props.cookies && props.cookies.JWT) || false; - return React.createElement(provideContext(component), props); - }; -}; diff --git a/app/scripts/client.js b/app/scripts/client.js deleted file mode 100644 index 54cdf61f0a..0000000000 --- a/app/scripts/client.js +++ /dev/null @@ -1,102 +0,0 @@ -/*global window, process, require */ -'use strict'; - -// Needed to shim Object.assign (used by 3rd party libs) -import 'babel-core/polyfill'; - -import React from 'react'; -import { render } from 'react-dom'; -import { Router } from 'react-router'; -import FluxRouter from './fluxibleRouter'; -import createHistory from 'history/lib/createBrowserHistory'; -import app from './app'; -import navigateAction from './actions/navigate'; -import JWTStore from './stores/JWTStore'; -import bootstrapCreateElement from './bootstrapCreateElement'; - -// This renders a Provider for basic flux integration -import { Provider } from 'react-redux'; -import reducers from './reducers'; -import enhancedCreateStore from './reduxStore'; - -require('velocity-animate'); -require('velocity-animate/velocity.ui'); - -let oDebug = require('debug'); -if (process.env.ENV !== 'production') { - oDebug.enable('hub:*'); -} -const debug = oDebug('hub:client'); -const dehydratedState = window.App; // Sent from the server - -if (process.env.ENV !== 'production') { - window.React = React; // For chrome dev tool support -} - -let history = createHistory(); -let unlisten = history.listen(function (location) { - debug('unlisten', location.pathname); -}); - -// Plug a History into the actionContext -let pluginRouter = Router; -app.plug({ - name: 'HistoryPlugin', - plugContext() { - return { - plugActionContext(actionContext) { - actionContext.history = history; - } - }; - } -}); - -function onUpdate(context) { - return (state, callback) => { - debug('at least the second render'); - if (state) { - if (!state.jwt) { - let jwtStore = context.getComponentContext().getStore(JWTStore); - state.jwt = jwtStore.getJWT(); - } - context.executeAction(navigateAction, state, callback); - } - }; -} - -function renderApp(context) { - const mountNode = document.getElementById('app'); - const Routes = app.getComponent(); - - // context.reduxStore works client-side as we're setting this directly - // below in rehydrate. - const jsx = ( - - - - ); - - return render(jsx, mountNode, () => { debug('React Rendered'); }); -} - -// The callback is called after the app has rehydrated any plugins; -// our redux plugin neets to create the store itself. -app.rehydrate(dehydratedState, function(err, context) { - debug('rehydrating app'); - if (err) { - throw err; - } - - // Create a new store and save it to Fluxible's app context. - context.reduxStore = enhancedCreateStore(reducers); - - window.context = context; - debug('supposedly the first render'); - // Don't call the action on the first render on top of the server rehydration - // Otherwise there is a race condition where the action gets executed before - // render has been called, which can cause the checksum to fail. - renderApp(context); -}); diff --git a/app/scripts/components/AddRepo.css b/app/scripts/components/AddRepo.css deleted file mode 100644 index f70fa38675..0000000000 --- a/app/scripts/components/AddRepo.css +++ /dev/null @@ -1,5 +0,0 @@ -@import 'dux/css/box.css'; - -.contentWrapper { - margin-top: var(--default-margin); -} diff --git a/app/scripts/components/AddRepo.jsx b/app/scripts/components/AddRepo.jsx deleted file mode 100644 index 09767f177e..0000000000 --- a/app/scripts/components/AddRepo.jsx +++ /dev/null @@ -1,256 +0,0 @@ -'use strict'; - -import React, { createClass, PropTypes } from 'react'; -import _ from 'lodash'; -import connectToStores from 'fluxible-addons-react/connectToStores'; - -import CreateRepositoryFormStore from 'stores/CreateRepositoryFormStore'; -import DUXInput from './common/DUXInput.jsx'; -import SimpleTextArea from './common/SimpleTextArea.jsx'; -import Route404 from './common/RouteNotFound404Page.jsx'; -import PrivateRepoUsageStore from 'stores/PrivateRepoUsageStore.js'; -import RepositoryNameInput from 'common/RepositoryNameInput.jsx'; -import createRepository from 'actions/createRepository'; -import updateAddRepositoryFormField from 'actions/updateAddRepositoryFormField'; -import getSettingsData from 'actions/getSettingsData'; -import { STATUS } from 'stores/common/Constants'; -import { SplitSection } from 'common/Sections'; - -import Markdown from '@dux/element-markdown'; -import Card, { Block } from '@dux/element-card'; -import { PageHeader, Button } from 'dux'; -import styles from './AddRepo.css'; - -var debug = require('debug')('AddRepositoryForm'); - -var AddRepositoryForm = createClass({ - displayName: 'AddRepositoryForm', - contextTypes: { - executeAction: PropTypes.func.isRequired - }, - propTypes: { - JWT: PropTypes.string.isRequired, - createRepoFormStore: PropTypes.shape({ - fields: PropTypes.object.isRequired, - values: PropTypes.object.isRequired, - namespaces: PropTypes.arrayOf(PropTypes.string.isRequired).isRequired, - globalFormError: PropTypes.string - }), - privateRepoUsage: PropTypes.shape({ - privateRepoAvailable: PropTypes.number.isRequired - }) - }, - getInitialState: function() { - return { - currentNamespace: this.props.createRepoFormStore.values.namespace - }; - }, - _handleCreate: function(e) { - e.preventDefault(); - - var newRepo = { - namespace: this.state.currentNamespace, - name: this.props.createRepoFormStore.values.name.toLowerCase(), - description: this.props.createRepoFormStore.values.description, - full_description: this.props.createRepoFormStore.values.full_description, - is_private: this.props.createRepoFormStore.values.is_private === 'private' - }; - - this.context.executeAction(createRepository, - { - jwt: this.props.JWT, - repository: newRepo - }); - }, - _onChange(fieldKey) { - let _this = this; - return (e) => { - if (fieldKey === 'namespace') { - this.setState({ - currentNamespace: e.target.value - }); - this.context.executeAction(getSettingsData, { - JWT: _this.props.JWT, - username: e.target.value, - repoType: 'regular' - }); - } - this.context.executeAction(updateAddRepositoryFormField, { - fieldKey, - fieldValue: e.target.value - }); - }; - }, - _getCurrentQueryNamespace() { - //Check if user has passed in namespace as query | verify if they have access to it - var currentNamespace = this.props.location.query.namespace; - if (!_.includes(this.props.createRepoFormStore.namespaces, currentNamespace)) { - currentNamespace = this.props.createRepoFormStore.values.namespace; - } - return currentNamespace; - }, - componentDidMount() { - this.setState({ - currentNamespace: this._getCurrentQueryNamespace() - }); - }, - _renderCreateForm() { - const { createRepoFormStore } = this.props; - - var globalFormError = (
); - if(createRepoFormStore.globalFormError) { - globalFormError = ( -
{createRepoFormStore.globalFormError}
- ); - } - - var nameError = (

); - var nameClass = ''; - if(createRepoFormStore.fields.name.hasError) { - nameError = ( -

- {createRepoFormStore.fields.name.error + - ' No spaces and special characters other than - and . are allowed. Repo names should not begin/end with a . or - .'} -

- ); - nameClass = 'text-error'; - } - - var fullDescriptionError = (

); - var fullDescriptionClass = 'large-12 columns'; - if(createRepoFormStore.fields.full_description.hasError) { - fullDescriptionError = ( -

{createRepoFormStore.fields.full_description.error}

- ); - fullDescriptionClass = 'large-12 columns form-error'; - } - - var descriptionError = (

); - var descriptionClass = 'large-12 columns'; - if(createRepoFormStore.fields.description.hasError) { - descriptionError = ( -

{createRepoFormStore.fields.description.error}

- ); - descriptionClass = 'large-12 columns form-error'; - } - var defaultValue = createRepoFormStore.values.is_private ? 'private' : 'public'; - var errText = ''; - if (createRepoFormStore.fields.is_private.hasError) { - errText = - - {createRepoFormStore.fields.is_private.error} - ; - } - const subtitleContent = `1. Choose a namespace *(Required)* -2. Add a repository name *(Required)* -3. Add a short description -4. Add markdown to the full description field -5. Set it to be a private or public repository`; - - return ( - {subtitleContent}}> -
- {globalFormError} -
-
- - {nameError} -
- -
-
- - {descriptionError} -
-
- -
-
- - {fullDescriptionError} -
-
- -
-
- Visibility - - {errText} -
-
- - - -
-
-
- ); - }, - render() { - if (!this.props.JWT) { - return (); - } else { - let content = ( -
-
- - -

Something went wrong!

-

- We were unable to populate your user namespaces. - If this issue persists, please contact support@docker.com -  or file an issue at hub-feedback on github -

-
-
-
-
- ); - if ( this.props.createRepoFormStore.namespaces && this.props.createRepoFormStore.namespaces.length > 0 ) { - content = ( -
- {this._renderCreateForm()} -
- ); - } - - return ( -
- - { content } -
- ); - } - } -}); - -export default connectToStores(AddRepositoryForm, - [ - CreateRepositoryFormStore - ], - function({ getStore }, props) { - return { - createRepoFormStore: getStore(CreateRepositoryFormStore).getState() - }; - }); diff --git a/app/scripts/components/Application.css b/app/scripts/components/Application.css deleted file mode 100644 index 125199c54b..0000000000 --- a/app/scripts/components/Application.css +++ /dev/null @@ -1,6 +0,0 @@ -.main{ - display:flex; - flex-direction: column; - justify-content: flex-start; - min-height: 100vh; -} diff --git a/app/scripts/components/Application.jsx b/app/scripts/components/Application.jsx deleted file mode 100644 index 8601467ed6..0000000000 --- a/app/scripts/components/Application.jsx +++ /dev/null @@ -1,75 +0,0 @@ -'use strict'; - -const debug = require('debug')('Application'); -import ApplicationStore from '../stores/ApplicationStore'; -import JWTStore from '../stores/JWTStore'; -import UserStore from '../stores/UserStore.js'; -import React, { PropTypes, Component, cloneElement } from 'react'; -import Welcome from './Welcome.jsx'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import Spinner from './Spinner.jsx'; -import MainNav from './Nav.jsx'; -import styles from './Application.css'; -import _ from 'lodash'; - -class Application extends Component { - - render() { - //Destructure router and props - const { JWT, user, location, history, params } = this.props; - //We use !JWT to check if a user is in logged out state - debug(this.props); - if (!JWT && location.pathname === '/') { - debug('Out Home'); - return ( -
- - -
- ); - } else if (history.isActive('/login/') || history.isActive('/reset-password/')) { - debug('Application'); - return ( -
- {this.props.children} -
- ); - } else { - debug('Root'); - const ifJWT = JWT ? JWT : ''; - return ( -
- - {this.props.children && cloneElement(this.props.children, { - JWT: ifJWT, - user, - location - })} -
- ); - } - } -} - -export default connectToStores(Application, - [ - ApplicationStore, - JWTStore, - UserStore - ], - ({ getStore }, props) => { - return _.merge({}, - getStore(ApplicationStore).getState(), - { - JWT: getStore(JWTStore).getJWT(), - user: getStore(UserStore).getState() - }); - }); diff --git a/app/scripts/components/Badge.jsx b/app/scripts/components/Badge.jsx deleted file mode 100644 index 254a2cf6eb..0000000000 --- a/app/scripts/components/Badge.jsx +++ /dev/null @@ -1,17 +0,0 @@ -'use strict'; - -import React from 'react'; - -var Badge = React.createClass({ - render: function() { - var name = this.props.name; - var category = this.props.category; - return ( -
-
{name}
-
- ); - } -}); - -module.exports = Badge; diff --git a/app/scripts/components/CSEngineDownloadPage.css b/app/scripts/components/CSEngineDownloadPage.css deleted file mode 100644 index ef0891456a..0000000000 --- a/app/scripts/components/CSEngineDownloadPage.css +++ /dev/null @@ -1,3 +0,0 @@ -.pageWrapper { - padding-top: 1.25rem; -} \ No newline at end of file diff --git a/app/scripts/components/CSEngineDownloadPage.jsx b/app/scripts/components/CSEngineDownloadPage.jsx deleted file mode 100644 index a9741e14b3..0000000000 --- a/app/scripts/components/CSEngineDownloadPage.jsx +++ /dev/null @@ -1,20 +0,0 @@ -'use strict'; - -import React, { PropTypes, Component } from 'react'; -import CSEngineBox from 'common/CSEngineBox'; -import styles from './CSEngineDownloadPage.css'; - -//publicly accessible page for only CS engine download -export default class CSEngineDownloadPage extends Component { - render() { - return ( -
-
-
- -
-
-
- ); - } -} diff --git a/app/scripts/components/CreateButton.jsx b/app/scripts/components/CreateButton.jsx deleted file mode 100644 index 458fe26762..0000000000 --- a/app/scripts/components/CreateButton.jsx +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; -import React from 'react'; -import _ from 'lodash'; -import { FluxibleMixin } from 'fluxible'; - -var CreateButton = React.createClass({ - propTypes: { - what: React.PropTypes.string.isRequired - }, - getDefaultProps: function() { - return { - what: '' - }; - }, - render: function() { - return ( - - ); - } -}); - -module.exports = CreateButton; diff --git a/app/scripts/components/DashboardWrapper.css b/app/scripts/components/DashboardWrapper.css deleted file mode 100644 index d22ed0dc67..0000000000 --- a/app/scripts/components/DashboardWrapper.css +++ /dev/null @@ -1,4 +0,0 @@ -.select { - margin-top: 6px; - min-width: 200px; -} diff --git a/app/scripts/components/DashboardWrapper.jsx b/app/scripts/components/DashboardWrapper.jsx deleted file mode 100644 index 31627c12b6..0000000000 --- a/app/scripts/components/DashboardWrapper.jsx +++ /dev/null @@ -1,98 +0,0 @@ -'use strict'; - -import React, { Component, PropTypes, cloneElement } from 'react'; -import { Link } from 'react-router'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import trunc from 'lodash/string/trunc'; -import PrivateReposBlock from './dashboards/PrivateRepoStatusBlock.jsx'; -import DashboardNamespacesStore from '../stores/DashboardNamespacesStore'; -import { SecondaryNav } from 'dux'; -import GravatarOption from './gravatar/GravatarOption'; -import GravatarValue from './gravatar/GravatarValue'; -import FA from './common/FontAwesome'; -import LiLink from './common/LiLink'; -import Select from 'react-select'; -import styles from './DashboardWrapper.css'; - -const { array, func, shape, string } = PropTypes; -const debug = require('debug')('DashboardWrapper'); - -class DashboardWrapper extends Component { - - static propTypes = { - //currentUserContext (dashboard user context, could be logged in user or one of the user's orgs) - //namespaces (all the namespaces that the user can look at) - dashboardNamespaces: shape({ - currentUserContext: string.isRequired, - namespaces: array.isRequired - }), - JWT: string, - user: shape({ - username: string - }) - } - - mkOptions = (arr) => { - return arr.map((namespace) => { - return {value: namespace, label: trunc(namespace, 16)}; - }); - }; - - changeContext = ({value: namespace, label}) => { - if (namespace) { - const { dashboardNamespaces, user, history, location } = this.props; - let currentPage = parseInt(location.query.page, 10); - if (dashboardNamespaces.currentUserContext === namespace) { - //do nothing - debug('doing nothing. Namespace is the same'); - } else if (user.username === namespace) { - //navigate to home - debug('navigate to home; its a user namespace'); - history.pushState(null, '/', {page: currentPage || 1}); - } else { - //navigate to org dashboard - debug('navigate to org dashboard'); - history.pushState(null, `/u/${namespace}/dashboard/`); - } - } - }; - - render() { - const { children, dashboardNamespaces, JWT, user } = this.props; - return ( -
- -
    -
  • - -
  • - - Repositories - - - Teams - - { Billing } - { Settings } -
- -
- {cloneElement(children, { - JWT, - user: org, - isOwner, - currentUserContext - })} -
- ); - } else { - return ( - - ); - } - } -} - -export default connectToStores(OrgDashboardWrapper, - [ - DashboardNamespacesStore, - OrganizationStore - ], - function({ getStore }, props) { - return merge( - {}, - getStore(DashboardNamespacesStore).getState(), - {org: getStore(OrganizationStore).getCurrentOrg()} - ); - }); diff --git a/app/scripts/components/Register.css b/app/scripts/components/Register.css deleted file mode 100644 index 9a60f5fef6..0000000000 --- a/app/scripts/components/Register.css +++ /dev/null @@ -1,11 +0,0 @@ -@import "dux/css/colors.css"; -@import "dux/css/box.css"; - -/* Upper Section */ -.header { - background: var(--docker-dark); - color: var(--smoke); - min-height: 560px; - height: 100%; - padding-top: 75px; -} diff --git a/app/scripts/components/Register.jsx b/app/scripts/components/Register.jsx deleted file mode 100644 index 13b71b6b9f..0000000000 --- a/app/scripts/components/Register.jsx +++ /dev/null @@ -1,23 +0,0 @@ -'use strict'; - -import styles from './Register.css'; - -import React, { Component, PropTypes } from 'react'; -import SignupForm from './welcome/SignupForm.jsx'; -var debug = require('debug')('Register'); - -export default class Register extends Component { - render() { - return ( -
-
- -
- -
- -
-
- ); - } -} diff --git a/app/scripts/components/RepositoryPageWrapper.css b/app/scripts/components/RepositoryPageWrapper.css deleted file mode 100644 index 87f9cfb4d5..0000000000 --- a/app/scripts/components/RepositoryPageWrapper.css +++ /dev/null @@ -1,31 +0,0 @@ -@import "dux/css/colors.css"; - -.repoLabel { - text-transform: uppercase; - font-weight: 500; -} - -.repoHeader { - border-bottom: 1px solid #c1c9d1; - background-color: white; - padding-top: 1.6rem; - padding-bottom: 1.2rem; -} -.repoTitle { - color: #555; - margin-bottom: 0; - font-weight: 300; -} -.repoSubtitle { - color: var(--secondary-5); - display: block; -} - -.repoStar { - cursor: pointer; - color: var(--secondary-3); - margin-left: 1rem; - font-size: xx-large; -} - -.private {} \ No newline at end of file diff --git a/app/scripts/components/RepositoryPageWrapper.jsx b/app/scripts/components/RepositoryPageWrapper.jsx deleted file mode 100644 index dd3ca9bba8..0000000000 --- a/app/scripts/components/RepositoryPageWrapper.jsx +++ /dev/null @@ -1,184 +0,0 @@ -'use strict'; - -import styles from './RepositoryPageWrapper.css'; -import React, { PropTypes, Component, cloneElement } from 'react'; -const { string, number, bool, shape, array, object, func } = PropTypes; -import { Link } from 'react-router'; -import _ from 'lodash'; -import includes from 'lodash/collection/includes'; -import merge from 'lodash/object/merge'; -import omit from 'lodash/object/omit'; -import words from 'lodash/string/words'; -import moment from 'moment'; -import FA from 'common/FontAwesome'; -const REPOSTATUS = require('../stores/repostore/Constants').STATUS; - -import RouteNotFound404Page from 'common/RouteNotFound404Page'; -import toggleStarred from '../actions/toggleStarred'; -import RepositoryPageStore from '../stores/RepositoryPageStore'; -import DashboardNamespacesStore from '../stores/DashboardNamespacesStore'; -import connectToStores from 'fluxible-addons-react/connectToStores'; - -var debug = require('debug')('RepositoryPageWrapper'); - -class Privacy extends Component { - static propTypes = { - isOfficial: bool.isRequired, - isPrivate: bool.isRequired, - isAutomated: bool.isRequired - } - render() { - const publicOrPrivate = this.props.isPrivate ? 'Private' : 'Public'; - if (this.props.isOfficial) { - return ( -
-
Official Repository
-
- ); - } else if (this.props.isAutomated) { - return ( -
-
{publicOrPrivate} | Automated Build
-
- ); - } else { - return ( -
-
{publicOrPrivate} Repository
-
- ); - } - } -} - -class StarRepo extends Component { - static propTypes = { - hasStarred: bool.isRequired, - toggleStar: func.isRequired - } - render() { - const { toggleStar, hasStarred } = this.props; - - let toggle = toggleStar(true); - let icon = 'fa-star-o'; - - if (hasStarred) { - toggle = toggleStar(false); - icon = 'fa-star'; - } - - return ( - - - - ); - } -} - -class RepositoryPageWrapper extends Component { - static propTypes = { - description: string.isRequired, - fullDescription: string.isRequired, - hasStarred: bool.isRequired, - isPrivate: bool.isRequired, - isAutomated: bool.isRequired, - lastUpdated: string, - name: string.isRequired, - namespace: string.isRequired, - status: number.isRequired, - canEdit: bool.isRequired, - comments: shape({ - count: number.isRequired, - results: array.isRequired - }), - user: object, - JWT: string, - history: object.isRequired, - ownedNamespaces: array.isRequired, - namespaces: array, - currentUserContext: string - } - - static contextTypes = { - executeAction: func.isRequired - } - - _toggleStar = status => e => { - e.preventDefault(); - var repoShortName = this.props.namespace + '/' + this.props.name; - this.context.executeAction(toggleStarred, { - jwt: this.props.JWT, - repoShortName: repoShortName, - status: status - }); - }; - - render() { - if (this.props.STATUS === REPOSTATUS.REPO_NOT_FOUND) { - return ; - } - - let privacy; - - //Redirect to user profile page if public user, if org (and owner) redirect to dashboard, if public org, org profile page - let namespaceLink; - var {namespace, ownedNamespaces, user} = this.props; - if (includes(ownedNamespaces, this.props.namespace) && namespace !== user.username) { - namespaceLink = {this.props.namespace}; - } else { - namespaceLink = {this.props.namespace}; - } - const starRepo = ; - let repoShortName = ( -
- {namespaceLink} - / - {this.props.name} - {starRepo} -
- ); - if (this.props.isOfficial || this.props.namespace === 'library') { - repoShortName = ( -
- {this.props.name} - {starRepo} -
- ); - } - - let computedLastUpdated = 'never'; - if (this.props.lastUpdated) { - computedLastUpdated = moment(this.props.lastUpdated).fromNow(); - } - - return ( -
-
-
-
- -

{repoShortName}

- Last pushed: {computedLastUpdated} -
-
-
- {this.props.children && cloneElement(this.props.children, omit(this.props, 'children'))} -
- ); - } -} - -export default connectToStores(RepositoryPageWrapper, - [ - RepositoryPageStore, - DashboardNamespacesStore - ], - ({ getStore }, props) => { - return merge({}, - getStore(DashboardNamespacesStore).getState(), - getStore(RepositoryPageStore).getState()); - }); diff --git a/app/scripts/components/Routes.css b/app/scripts/components/Routes.css deleted file mode 100644 index 2f483ab999..0000000000 --- a/app/scripts/components/Routes.css +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Adding global css in Routes.css to load class names as-is so we don't have local processed classes - * - * vendor overrides - * ---------------- - * 1. react-select [styles/vendor-overrides/react-select.css] - * 2. rc-tooltip [styles/vendor-overrides/rc-tooltip.css] - * - */ -:global { - @import '../../styles/vendor-overrides/react-select.css'; - /** Default styles from rc-tooltip which will be overwritten **/ - @import "rc-tooltip/assets/bootstrap_white.css"; - @import '../../styles/vendor-overrides/rc-tooltip.css'; -} diff --git a/app/scripts/components/Routes.jsx b/app/scripts/components/Routes.jsx deleted file mode 100644 index 713b0d8100..0000000000 --- a/app/scripts/components/Routes.jsx +++ /dev/null @@ -1,212 +0,0 @@ -'use strict'; - -import { - Route, Redirect, IndexRoute -} from 'react-router'; -import React from 'react'; -import styles from './Routes.css'; - -const Account = require('./account/Account'); -const AccountSettings = require('./account/AccountSettings'); -const AddOrganizationForm = require('./account/AddOrganizationForm'); -import AddRepo from './AddRepo'; -const Application = require('./Application'); -const Autobuild = require('./repositories/Autobuild'); -const AutobuildIndex = require('./repositories/AutobuildIndex.jsx'); -const AutoBuildSetupForm = require('./repositories/AutoBuildSetupForm'); -const BillingPlans = require('./account/BillingPlans'); -import UpdateBillingInfo from './account/UpdateBillingInfo'; -import ChangePassSuccess from './welcome/ChangePassSuccess'; -import CreateBillingSubscription from './account/CreateBillingSubscription'; -import ConvertToOrg from './account/ConvertToOrg'; -import CSEngineDownloadPage from './CSEngineDownloadPage'; -import DashboardContribs from './dashboards/Contribs'; -import DashboardWrapper from './DashboardWrapper'; -import DashboardRepos from './dashboards/Repos'; -import DashboardStars from './dashboards/Stars'; -import orgDashTeams from './orgdashboards/Teams'; -import Dockerfile from './repo/repo_details/Dockerfile'; -import Explore from './Explore'; -import EnterpriseSubscriptions from './enterprise/Enterprise'; -import ServerTrial from './enterprise/EnterpriseTrial'; -import EnterpriseTrialSuccess from './enterprise/EnterpriseTrialSuccess'; -import EULA from './EULA'; -import EnterpriseTrialTerms from './enterprise/EnterpriseTrialTerms.jsx'; -import ForgotPassword from './welcome/ForgotPass'; -import GithubLinkScopes from './account/services/GithubLinkScopes'; -import Help from './help/Help'; -import Licenses from './account/Licenses'; -const LinkedAccountSourcesForm = require('./repositories/LinkedAccountSourcesForm'); -const LinkedServices = require('./account/LinkedServices'); -import Login from './Login'; -import Members from './orgdashboards/Members'; -const NotificationsSettings = require('./account/NotificationsSettings'); -const OrganizationProfile = require('./account/orgs/OrganizationProfile'); -const OrganizationSettings = require('./account/OrganizationSettings'); -const OrganizationSummary = require('./account/OrganizationSummary'); -import OrgDashboardWrapper from './OrgDashboardWrapper'; -import Register from './Register'; -import RepositorySettingsBuilds from './repo/repoSettings/Builds'; -import RepositorySettingsCollaborators from './repo/repoSettings/CollaboratorsWrapper.jsx'; -import RepositorySettingsMain from './repo/repoSettings/SettingsMain'; -import RepositorySettingsWebhooks from './repo/repoSettings/webhooks'; -import RepositorySettingsWrapper from './repo/RepositorySettingsWrapper'; -import RepositoryDetailsBuildDetails from './repo/repo_details/BuildDetails'; -import RepositoryDetailsBuildLogs from './repo/repo_details/BuildLogs'; -import RepositoryDetailsInfo from './repo/repo_details/Info'; -import RepositoryDetailsTags from './repo/repo_details/Tags'; -import RepositoryDetailsScannedTag from './repo/repo_details/ScannedTag'; -import RepositoryDetailsWrapper from './repo/RepositoryDetailsWrapper'; -import RepositoryPageWrapper from './RepositoryPageWrapper'; -import ResetPassword from './welcome/ResetPass'; -import RouteNotFound404Page from './common/RouteNotFound404Page'; -const Search = require('./search/Search'); -const UserStars = require('./userWrapper/UserStars'); -const User = require('./Users'); //Unused -import UserProfileWrapper from './UserProfileWrapper'; -import UserProfileRepos from './userprofile/Repos'; - -// NOTE: Provider right now doesn't work easily with fluxible's render pipeline. -// Even though we add the as a root element to Routes.jsx: -// -// module.exports = ( -// -// { routes } -// -// ); -// -// Fluxible doesn't render the root Provider component; it renders the first -// component which connects to fluxibles stores. -// -// FIX: We've instead added as the base class that fluxibleRouter -// renders -// -// TODO: When we rip out Fluxible add as a top level component here. - -var routes = ( - - {/* Login and Password */} - - - - - - {/* Currently logged in user Dashboard */} - - - - - - - {/* Public user profile */} - - - - - - {/* Organization Dashboard */} - - - - - - - - - - {/* Organizations Summary and Add Route */} - - - - - - {/* Add a repository route */} - - - {/* Autobuild creation related routes */} - - - - - - - - - {/* Github linking related route | the scope selection screen */} - - - {/* Official repositories route | TODO: add library/:name */} - - - - - - - {/* THIS ROUTE IS A DUPLICATE OF /u/:user/. WHY IS THIS HERE??? */} - - - - - - - - - - - - - - - - - - - - - - {/* User Account Settings */} - - - - - - - - - - - - - - - - - {/* Billing/Enterprise/Subscription related routes */} - - - {/* TODO: @camacho 2/9/16 - remove routes after 1 week to give time for loaded clients to be updated*/} - - - - - - - - - - {/* Some publicly available routes to explore, search and ask for help */} - - - - - - {/* Handle 404 for bad routes | If no route matches, render a 404 page */} - - -); - -module.exports = routes; diff --git a/app/scripts/components/Spinner.jsx b/app/scripts/components/Spinner.jsx deleted file mode 100644 index 9a90885587..0000000000 --- a/app/scripts/components/Spinner.jsx +++ /dev/null @@ -1,20 +0,0 @@ -'use strict'; -const React = require('react'); - -var Spinner = React.createClass({ - render: function() { - return (
-
-
-
-
-
-
-
-
-
-
); - } -}); - -module.exports = Spinner; diff --git a/app/scripts/components/StatsComponent.jsx b/app/scripts/components/StatsComponent.jsx deleted file mode 100644 index f285424eba..0000000000 --- a/app/scripts/components/StatsComponent.jsx +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; -import React from'react'; - -//TODO: add to component, currently just use a placeholder docker icon -//
    -//
  • {this.props.value}
  • -//
  • {this.props.statsItemName}
  • -//
- -var StatsComponent = React.createClass({ - displayName: 'StatsComponent', - propTypes: { - value: React.PropTypes.string.isRequired, - statsItemName: React.PropTypes.string.isRequired - }, - render: function() { - return ( -
-

{this.props.value}

-

{this.props.statsItemName}

-
- ); - } -}); - -module.exports = StatsComponent; diff --git a/app/scripts/components/UserProfileWrapper.css b/app/scripts/components/UserProfileWrapper.css deleted file mode 100644 index 4059138564..0000000000 --- a/app/scripts/components/UserProfileWrapper.css +++ /dev/null @@ -1,27 +0,0 @@ -@import "dux/css/colors.css"; -@import "dux/css/box.css"; - -.heading { - padding-left: 1rem; -} - -.userinfo { - border-top: 1px solid var(--secondary-5); - border-bottom: 1px solid var(--secondary-5); - padding: 1rem; - margin-right: 1rem; - list-style-type: none; -} - - .item { - width: 260px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.gravatar { - border: 1px solid var(--secondary-5); - margin: 1rem 0; - border-radius: 3px; -} diff --git a/app/scripts/components/UserProfileWrapper.jsx b/app/scripts/components/UserProfileWrapper.jsx deleted file mode 100644 index f5b7186c93..0000000000 --- a/app/scripts/components/UserProfileWrapper.jsx +++ /dev/null @@ -1,124 +0,0 @@ -'use strict'; - -import React, { PropTypes, createClass, cloneElement } from 'react'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import UserProfileStore from '../stores/UserProfileStore'; -import RepositoriesList from './common/RepositoriesList'; -import RouteNotFound404Page from './common/RouteNotFound404Page'; -import moment from 'moment'; -import { SecondaryNav } from 'dux'; -import FA from 'common/FontAwesome'; -import { Link } from 'react-router'; -import _ from 'lodash'; -import styles from './UserProfileWrapper.css'; - -var debug = require('debug')('UserProfileWrapper'); - -var UserShape = { - id: PropTypes.string.isRequired, - username: PropTypes.string, - orgname: PropTypes.string, - full_name: PropTypes.string.isRequired, - location: PropTypes.string.isRequired, - company: PropTypes.string.isRequired, - profile_url: PropTypes.string.isRequired, - date_joined: PropTypes.string.isRequired, - gravatar_url: PropTypes.string.isRequired -}; - -var ProfileCard = createClass({ - displayName: 'ProfileCard', - propTypes: UserShape, - render() { - var gravatar = this.props.gravatar_url; - /** - * If the gravatar has a size equal to 80 in the url, - * change it to 512. This is a HACK. - */ - if(this.props.gravatar_url && this.props.gravatar_url.match(/s=80/)) { - gravatar = gravatar.replace('s=80', 's=512'); - } - - var maybeLocation = null; - var maybeCompany = null; - var maybeProfileUrl = null; - - if (this.props.location) { - maybeLocation =
  • {this.props.location}
  • ; - } - if (this.props.maybeCompany) { - maybeCompany =
  • {this.props.company}
  • ; - } - if (this.props.profile_url) { - maybeProfileUrl =
  • {this.props.profile_url}
  • ; - } - - return ( -
    -
    -
    - -
    -
    -
    -

    {this.props.username || this.props.orgname}

    -

    {this.props.full_name}

    -
      - {maybeLocation} - {maybeCompany} - {maybeProfileUrl} -
    • Joined {moment(this.props.date_joined).format('MMMM YYYY')}
    • -
    -
    -
    - ); - } -}); - -var UserProfile = createClass({ - displayName: 'UserProfile', - propTypes: { - user: PropTypes.shape(UserShape) - }, - render() { - if(this.props.STATUS === '404' || _.isEmpty(this.props.user)) { - return (); - } else { - let namespace; - var maybeStars = null; - if(this.props.user.orgname) { - namespace = this.props.user.orgname; - } else { - namespace = this.props.user.username; - maybeStars = (
  • Stars
  • ); - } - return ( -
    - -
      -
    • Repos
    • - {maybeStars} -
    -
    -
    -
    - -
    -
    - {this.props.children && cloneElement(this.props.children, {user: this.props.user})} -
    -
    -
    - ); - } - } -}); - -export default connectToStores(UserProfile, - [ - UserProfileStore - ], - function({ getStore }, props) { - return getStore(UserProfileStore) - .getState(); - }); diff --git a/app/scripts/components/Users.jsx b/app/scripts/components/Users.jsx deleted file mode 100644 index 1e173210da..0000000000 --- a/app/scripts/components/Users.jsx +++ /dev/null @@ -1,60 +0,0 @@ -'use strict'; -/** -TODO: UNUSED COMPONENTS. SHOULD REMOVE -*/ -import React from 'react'; -import { Link } from 'react-router'; - -var UserPage = React.createClass({ - getDefaultProps: function() { - return { - user: {}, - JWT: '' - }; - }, - render: function() { - return ( -
    - This will be the base wrapper of the 'Users' page where either your or another users profile will appear
    - This will let you see your public facing page at /u/username/ too
    - 'Your' homepage/dashboard will live at /home/
    - -
    - ); - } -}); - -var RootUser = React.createClass({ - render: function() { - return ( -
    -

    - This is root user page.
    - When not looking at a specific user or an owned image
    - This will show a list of repos/images owned by the root user
    - This could be a image box of some sort -

    - ); - } -}); - -var User = React.createClass({ - // This page should either be the users home page or the view page for other users - render: function() { - return ( -
    -

    - This is the UID: {this.props.params.uid}
    - This is main user page.
    - This will show a list of repos/images owned by the user
    - -

    - ); - } -}); - -module.exports = { - userpage: UserPage, - rootuser: RootUser, - user: User -}; diff --git a/app/scripts/components/Welcome.css b/app/scripts/components/Welcome.css deleted file mode 100644 index 7c4be7573f..0000000000 --- a/app/scripts/components/Welcome.css +++ /dev/null @@ -1,86 +0,0 @@ -@import "dux/css/colors.css"; -@import "dux/css/box.css"; - -.flex{ - display:flex; - flex-direction: column; - justify-content: flex-start; - flex-grow: 1; -} - -.white { - background-color: var(--white); - flex-grow: 1; - padding-top: calc(var(--default-margin) * 1.5); -} - -.browse { - padding: .5rem 0; - text-align: center; -} - -/* Upper Section */ -.header { - background: var(--docker-dark); - color: var(--smoke); - min-height: 560px; - padding-top: 75px; -} - -.top { - padding: 0 var(--default-margin); -} - -.buildShipRun { - margin-top: 5rem; -} - -.subtext { - color: var(--white); -} - -.heading { - font-weight: 300; - color: var(--smoke); -} - -.headingHero { - composes: heading; - font-size: 3rem; - line-height: 0.8; -} - -.headingHeroAlt { - composes: headingHero; - color: var(--primary-color); -} - -/* Lower Section */ -.lowerHeading { - text-align: center; - margin-bottom: var(--default-margin); -} - -/* Company List */ -.companyRow { - padding: 1.5rem 0 .5rem 0; - margin-left: 0; - margin-right: 0; - margin-bottom: var(--default-margin); -} - -.companyLinkLi { - text-align: center; -} - -/* Footer */ -.footer { - text-align: center; - margin-top: var(--default-margin); -} - -.footerCopy { - color: var(--gray-3); - font-weight: 100; - font-size: .8rem; -} diff --git a/app/scripts/components/Welcome.jsx b/app/scripts/components/Welcome.jsx deleted file mode 100644 index 5a9a95bb0e..0000000000 --- a/app/scripts/components/Welcome.jsx +++ /dev/null @@ -1,113 +0,0 @@ -'use strict'; - -import styles from './Welcome.css'; - -import React, { createClass, PropTypes } from 'react'; -import LoginForm from './welcome/LoginForm.jsx'; -import SignupForm from './welcome/SignupForm.jsx'; -import { Link } from 'react-router'; -import classnames from 'classnames'; -import Button from '@dux/element-button'; -var debug = require('debug')('Welcome'); - -let LowerSection = createClass({ - displayName: 'LowerSection', - propTypes: { - companyList: PropTypes.arrayOf(PropTypes.object) - }, - getDefaultProps() { - return { - companyList: [ - {logo: 'harvard'}, - {logo: 'sony'}, - {logo: 'nordstrom'}, - {logo: 'oracle'}, - {logo: 'zendesk'}, - {logo: 'gopro'}, - {logo: 'autodesk'}, - {logo: 'cisco'}, - {logo: 'zenefits'}, - {logo: 'dollar-shave-club'}, - {logo: 'zipcar'}, - {logo: 'gilt'}, - {logo: 'adp'}, - {logo: 'makerbot'}, - {logo: 'oculus'}, - {logo: 'adobe'} - ] - }; - }, - mkCompanyLi({name, url, logo}) { - let img = `/public/images/customers/${logo}.png`; - return ( -
  • - -
  • - ); - }, - render() { - - let companyClasses = classnames({ - 'small-block-grid-4': true, - [styles.companyRow]: true - }); - - return ( -
    -

    The most innovative companies use Docker

    -
    -
    -
      - {this.props.companyList.map(str => { return this.mkCompanyLi(str); })} -
    -
    -
    -
    - ); - } -}); - -var Welcome = React.createClass({ - displayName: 'WelcomePage', - transitionExplore: function(e){ - e.preventDefault(); - this.props.history.pushState(null, '/explore/'); - }, - render() { - - let buildShipRun = classnames({ - 'large-8 columns': true, - [styles.buildShipRun]: true - }); - - return ( -
    -
    -
    - -
    -

    Build, Ship, & Run

    -

    Any App, Anywhere

    -

    Dev-test pipeline automation, 100,000+ free apps, public and private registries

    -
    - -
    - -
    - -
    -
    -
    - Browse Thousands of the most popular software tools in the Docker Image Library -
    -
    -
    -

    © 2016 Docker Inc.

    -
    -
    -
    - ); - } -}); - -module.exports = Welcome; diff --git a/app/scripts/components/account/Account.jsx b/app/scripts/components/account/Account.jsx deleted file mode 100644 index 0f30fa138b..0000000000 --- a/app/scripts/components/account/Account.jsx +++ /dev/null @@ -1,127 +0,0 @@ -'use strict'; - -import React, { PropTypes, cloneElement } from 'react'; -import { Link } from 'react-router'; -import FluxibleMixin from 'fluxible-addons-react/FluxibleMixin'; -import { SecondaryNav } from 'dux'; -import FA from 'common/FontAwesome'; -import LiLink from '../common/LiLink'; -import AccountSettingsLicensesStore from '../../stores/AccountSettingsLicensesStore'; -import EmailNotifStore from '../../stores/EmailNotifStore'; -import Route404 from '../common/RouteNotFound404Page.jsx'; - -let SettingNav = React.createClass({ - displayName: 'SettingsSecondaryNav', - mixins: [FluxibleMixin], - contextTypes: { - getStore: PropTypes.func.isRequired - }, - statics: { - storeListeners: { - onLicensesStoreChange: [AccountSettingsLicensesStore], - onNotifStoreChange: [EmailNotifStore] - } - }, - onLicensesStoreChange: function() { - let store = this.context.getStore(AccountSettingsLicensesStore); - this.setState({ - licenseAttempt: store.getAttempt() - }); - }, - onNotifStoreChange: function() { - let store = this.context.getStore(EmailNotifStore); - this.setState({ - notificationAttempt: store.getAttempt() - }); - }, - getInitialState() { - return { - licenseAttempt: false, - notificationAttempt: false - }; - }, - _showLicensesLoader() { - this.context.getStore(AccountSettingsLicensesStore).setAttempt(true); - this.setState({ - licenseAttempt: true - }); - }, - _showNotificationsLoader() { - this.context.getStore(EmailNotifStore).setAttempt(true); - this.setState({ - notificationAttempt: true - }); - }, - renderLicenses() { - var licensesElement; - if (!this.state.licenseAttempt) { - licensesElement = 'Licenses'; - } else { - licensesElement = (Licenses ); - } - return {licensesElement}; - }, - renderNotifications() { - var notificationsElement; - if (!this.state.notificationAttempt) { - notificationsElement = 'Notifications'; - } else { - notificationsElement = (Notifications ); - } - return {notificationsElement}; - }, - render() { - return ( - -
      - Account Settings - Billing & Plans - Linked Accounts & Services - {this.renderNotifications()} - {this.renderLicenses()} -
    -
    - ); - } -}); - -var Account = React.createClass({ - mixins: [FluxibleMixin], - propTypes: { - loggedOutElement: PropTypes.element - }, - contextTypes: { - getStore: PropTypes.func.isRequired - }, - render: function() { - - const { JWT, user, location } = this.props; - const path = location.pathname; - if (!JWT && path === '/account/billing-plans/create-subscription/') { - /* Handles the www.docker.com/pricing links to buy hub plans at URLs - * /account/billing-plans/create-subscription/?plan=index_personal_PLANSIZE - * when the user is logged out (has special redirects) - */ - return cloneElement(this.props.children, { - user: this.props.user, - JWT: this.props.JWT - }); - } else if (!JWT) { - return ( - - ); - } else { - return ( -
    - - {this.props.children && cloneElement(this.props.children, { - user: this.props.user, - JWT: this.props.JWT - })} -
    - ); - } - } -}); - -module.exports = Account; diff --git a/app/scripts/components/account/AccountSettings.css b/app/scripts/components/account/AccountSettings.css deleted file mode 100644 index f0a93fca61..0000000000 --- a/app/scripts/components/account/AccountSettings.css +++ /dev/null @@ -1,14 +0,0 @@ -@import "dux/css/box"; -@import "dux/css/colors"; - -.body { - margin-top: var(--default-margin); -} - -.margin { - margin: var(--default-margin); -} - -.visibility { - color: var(--black); -} \ No newline at end of file diff --git a/app/scripts/components/account/AccountSettings.jsx b/app/scripts/components/account/AccountSettings.jsx deleted file mode 100644 index 07193776eb..0000000000 --- a/app/scripts/components/account/AccountSettings.jsx +++ /dev/null @@ -1,138 +0,0 @@ -'use strict'; - -import React, { PropTypes } from 'react'; -import { Link } from 'react-router'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import _ from 'lodash'; - -import styles from './AccountSettings.css'; -import EmailForm from './forms/EmailForm'; -import AccountInfoForm from './forms/AccountInfoForm'; -import ChangePassForm from './forms/ChangePassForm'; -import convertToOrgAction from '../../actions/convertToOrganization'; -import toggleVisibility from '../../actions/toggleVisibility.js'; -import PrivateRepoUsageStore from '../../stores/PrivateRepoUsageStore.js'; -import { PageHeader, Button } from 'dux'; -import classnames from 'classnames'; -import { SplitSection } from '../common/Sections.jsx'; - -var debug = require('debug')('AccountSettings'); - -var Settings = React.createClass({ - contextTypes: { - executeAction: React.PropTypes.func.isRequired - }, - getDefaultProps: function() { - return { - user: {}, - JWT: '' - }; - }, - render: function() { - - return ( -
    - -
    -
    - - - - - -
    -
    -
    - ); - } -}); - -var DefaultVisibility = React.createClass({ - displayName: 'DefaultVisibility', - PropTypes: { - defaultRepoVisibility: PropTypes.string.isRequired - }, - contextTypes: { - executeAction: React.PropTypes.func.isRequired - }, - toggleClick(visibility) { - const _this = this; - return (e) => { - e.preventDefault(); - this.context.executeAction(toggleVisibility, _.merge(visibility, {JWT: _this.props.JWT, username: _this.props.username})); - }; - }, - render: function() { - - return ( -
    - Update the default visibility for your repositories.

    }> -
    -
    -
      -
    • - -
    • -
    • - -
    • -
    -
    -
    -
    -
    - ); - } -}); - -var ToOrgForm = React.createClass({ - _toOrgClick: function(e) { - e.preventDefault(); - this.props.history.pushState(null, '/account/convert-to-org/'); - }, - render: function() { - - if (this.props.userType === 'Organization') { - return ( -
    -
    -
    This is an Organization account for:
    -
    {this.props.username}
    -
    -
    -
    - ); - } else { - return ( - To use organization features you must convert your account from a "User" to an "Organization"

    }> -
    - -
    -
    - ); - } - } -}); - -export default connectToStores(Settings, - [ - PrivateRepoUsageStore - ], - function({ getStore }, props) { - return getStore(PrivateRepoUsageStore).getState(); - }); diff --git a/app/scripts/components/account/AddOrganizationForm.css b/app/scripts/components/account/AddOrganizationForm.css deleted file mode 100644 index f70fa38675..0000000000 --- a/app/scripts/components/account/AddOrganizationForm.css +++ /dev/null @@ -1,5 +0,0 @@ -@import 'dux/css/box.css'; - -.contentWrapper { - margin-top: var(--default-margin); -} diff --git a/app/scripts/components/account/AddOrganizationForm.jsx b/app/scripts/components/account/AddOrganizationForm.jsx deleted file mode 100644 index 63e658d507..0000000000 --- a/app/scripts/components/account/AddOrganizationForm.jsx +++ /dev/null @@ -1,96 +0,0 @@ -'use strict'; - -import React from 'react'; -import OrganizationStore from '../../stores/OrganizationStore'; -import AddOrganizationStore from '../../stores/AddOrganizationStore'; -import createOrganizationAction from '../../actions/createOrganization'; -import updateAddOrganizationFormField from '../../actions/updateAddOrganizationFormField'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -const debug = require('debug')('AddOrganizationForm'); -import SimpleInput from 'common/SimpleInput.jsx'; -import Button from '@dux/element-button'; -import styles from './AddOrganizationForm.css'; -import { SplitSection } from '../common/Sections.jsx'; - -var AddOrganizationForm = React.createClass({ - contextTypes: { - executeAction: React.PropTypes.func.isRequired - }, - propTypes: { - JWT: React.PropTypes.string.isRequired - }, - _onChange(fieldKey) { - return (e) => { - this.context.executeAction(updateAddOrganizationFormField, { - fieldKey, - fieldValue: e.target.value - }); - }; - }, - _handleCreate: function(e) { - e.preventDefault(); - /*eslint-disable camelcase */ - var newOrg = { - orgname: this.props.values.orgname.toLowerCase(), - full_name: this.props.values.full_name, - gravatar_email: this.props.values.gravatar_email, - company: this.props.values.company, - location: this.props.values.location, - profile_url: this.props.values.profile_url - /*eslint-enable camelcase */ - }; - this.context.executeAction(createOrganizationAction, { - jwt: this.props.JWT, - organization: newOrg - }); - }, - render: function() { - return ( -
    - - Organizations can have multiple Teams. Teams can have differing permissions. Namespace is - unique and this is where repositories for this organization will be created. -

    }> -
    -
    - - - - - - - - - -
    -
    - ); - } -}); - -export default connectToStores(AddOrganizationForm, - [ - AddOrganizationStore - ], - function({ getStore }, props) { - return getStore(AddOrganizationStore).getState(); - }); diff --git a/app/scripts/components/account/BillingPlans.css b/app/scripts/components/account/BillingPlans.css deleted file mode 100644 index d0d01aa909..0000000000 --- a/app/scripts/components/account/BillingPlans.css +++ /dev/null @@ -1,21 +0,0 @@ -@import 'dux/css/colors.css'; - -.body { - margin-top: 2rem; -} - -.error { - background: var(--primary-5); - color:white; -} - -.plansQuestion { - margin-bottom: 2rem; -} - -.questionTitle { - font-weight: 500; - color: var(--secondary-1); -} - -/*.questionAnswer {}*/ diff --git a/app/scripts/components/account/BillingPlans.jsx b/app/scripts/components/account/BillingPlans.jsx deleted file mode 100644 index 329daec409..0000000000 --- a/app/scripts/components/account/BillingPlans.jsx +++ /dev/null @@ -1,246 +0,0 @@ -/*global MktoForms2*/ - -'use strict'; - -import React, { PropTypes } from 'react'; -const { string, array, object, func, shape } = PropTypes; -import { Link } from 'react-router'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import isEmpty from 'lodash/lang/isEmpty'; - -import BillingPlansStore from '../../stores/BillingPlansStore'; -import updateSubscriptionPlanOrPackage from '../../actions/updateSubscriptionPlanOrPackage.js'; - -import PlansTable from './billingplans/Plans'; -import EnterpriseSubscriptions from './billingplans/EnterpriseSubscriptions.jsx'; -import BillingInfo from './billingplans/BillingInfo.jsx'; -import InvoiceTables from './billingplans/InvoiceTables.jsx'; -import styles from './BillingPlans.css'; -import { FullSection } from '../common/Sections.jsx'; -import Route404 from '../common/RouteNotFound404Page.jsx'; -import { PageHeader } from 'dux'; - -/* Marketo constants for the marketing survey form */ -const mktoFormId = 1317; -const mktoFormElemId = 'mktoForm_' + mktoFormId; -const mktoFormBaseUrl = 'https://app-sj05.marketo.com'; -const mktoFormMunchkinId = '929-FJL-178'; - -var BillingInfoPage = React.createClass({ - - contextTypes: { - executeAction: func.isRequired - }, - - PropTypes: { - JWT: string, - user: object, - currentPlan: shape({ - id: string, - plan: string, - package: string - }), - accountInfo: shape({ - account_code: string, - username: string, - email: string, - first_name: string, - last_name: string, - company_name: string - }), - billingInfo: shape({ - city: string, - state: string, - zip: string, - first_name: string, - last_name: string, - address1: string, - address2: string, - country: string - }), - plansError: string, - invoices: array, - unsubscribing: string, - updatePlan: string - }, - - stopSubscription(subscriptionType) { - /** - * UPDATE 4/6/16 "cloud_metered" is the new "free" plan instead of deleting - * per ticket HUB-2219 - */ - return () => { - const { JWT, user, currentPlan } = this.props; - const namespace = user.username || user.orgname; - let subscriptionData = { - JWT, - username: namespace, - subscription_uuid: currentPlan.subscription_uuid - }; - if (subscriptionType === 'plan') { - subscriptionData.plan_code = 'cloud_metered'; - if (currentPlan.package) { - // preserve package (like cloud_starter) if it exists - subscriptionData.package_code = currentPlan.package; - } - } else if (subscriptionType === 'package') { - // If you are removing a package, leave the plan alone - subscriptionData.plan_code = currentPlan.plan; - // Explicitly set null to remove - subscriptionData.package_code = null; - } - this.context.executeAction(updateSubscriptionPlanOrPackage, subscriptionData); - }; - }, - - showSurveyModal(subscriptionType) { - return () => { - if (typeof MktoForms2 === 'object' && - typeof MktoForms2.loadForm === 'function') { - MktoForms2.loadForm( - mktoFormBaseUrl, - mktoFormMunchkinId, - mktoFormId, - (form) => { - form.onSubmit(this.stopSubscription(subscriptionType)); - // Don't refresh the page after a successful submission. - // React component will re-render itself. - form.onSuccess(() => false); - form.vals({'Email': this.props.accountInfo.email}); - MktoForms2.lightbox(form).show(); - }); - } else { - // If for any reason there is a problem with the Marketo script, - // we shouldn't block the user from stopping his/her subscription. - this.stopSubscription(subscriptionType); - } - }; - }, - - getSurveyModalHtml() { - return ( -
    -
    -
    - ); - }, - - render: function() { - let plansIntro; - let plansFooter; - let errorSection; - const { - accountInfo, - billingInfo, - currentPlan, - invoices, - isOwner, - JWT, - plansError, - unsubscribing, - updatePlan, - user, - history - } = this.props; - if (accountInfo.newBilling) { - plansIntro = ( - -
    - The Docker Hub Registry is free to use for public repositories. Plans with private repositories are - available in different sizes. All plans allow collaboration with unlimited people. -
    -
    - ); - plansFooter = ( - -
    -
    What types of payment do you accept?
    -
    Credit card (Visa, MasterCard, Discover, or American Express).
    -
    -
    -
    Do I have to pay to use your service?
    -
    No, you only have to pay if you require one or more private repository.
    -
    -
    -
    Can I change my plan at a later time?
    -
    Yes, you can upgrade or downgrade at any time.
    -
    -
    -
    What if I need a larger plan?
    -
    Please contact our Sales team at sales@docker.com or call us toll free at 888-214-4258.
    -
    -
    - ); - } else { - plansIntro = (
    ); - plansFooter = (
    ); - } - if (plansError) { - errorSection = ( - -
    - There was an error trying to update your subscription. Please contact the Docker support team.
    - {plansError} -
    -
    - ); - } - const username = user.username || user.orgname || ''; - const isOrg = !!user.orgname; - - if (isOrg && !isOwner) { - return ( - - ); - } else { - /* - accountInfo.newBilling / billingInfo.newBilling - Means this is a brand new account without any information saved to the backend - */ - return ( -
    - -
    - {plansIntro} - {errorSection} - - {plansFooter}
    -
    - - - -
    - {this.getSurveyModalHtml()} -
    - ); - } - } -}); - -export default connectToStores(BillingInfoPage, - [BillingPlansStore], - function({ getStore }, props) { - return getStore(BillingPlansStore).getState(); - }); diff --git a/app/scripts/components/account/ConvertToOrg.css b/app/scripts/components/account/ConvertToOrg.css deleted file mode 100644 index ace3d024ff..0000000000 --- a/app/scripts/components/account/ConvertToOrg.css +++ /dev/null @@ -1,25 +0,0 @@ -@import 'dux/css/colors.css'; - -.body { - margin-top: 1rem; -} - -.toOrgContent { - margin-bottom: 1rem; -} - -.warning { - color: var(--primary-5); -} - -.center { - text-align: center; - margin-bottom: 1rem; -} - -.form { - padding-top: 1rem; - div { - margin-bottom: 0; - } -} \ No newline at end of file diff --git a/app/scripts/components/account/ConvertToOrg.jsx b/app/scripts/components/account/ConvertToOrg.jsx deleted file mode 100644 index 22545837e9..0000000000 --- a/app/scripts/components/account/ConvertToOrg.jsx +++ /dev/null @@ -1,145 +0,0 @@ -'use strict'; - -import React, { PropTypes } from 'react'; -import { Link } from 'react-router'; -import _ from 'lodash'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import classnames from 'classnames'; - -import DUXInput from '../common/DUXInput.jsx'; -import convertToOrgAction from '../../actions/convertToOrganization'; -import updateToOrgOwner from '../../actions/updateToOrgOwner.js'; -import ConvertToOrgStore from '../../stores/ConvertToOrgStore.js'; -import { PageHeader, Module } from 'dux'; -import Button from '@dux/element-button'; - -import { FullSection } from '../common/Sections.jsx'; - -import styles from './ConvertToOrg.css'; - -var debug = require('debug')('ConvertToOrg'); - -var _mkErrors = function(err, key) { - const errorClass = classnames({ - [ styles.center ]: true, - [ styles.warning ]: true - }); - return ( -
    - { err } -
    - ); -}; - -var ConvertToOrg = React.createClass({ - contextTypes: { - executeAction: PropTypes.func.isRequired - }, - propTypes: { - user: PropTypes.shape({ - username: PropTypes.string - }), - JWT: PropTypes.string, - convertError: PropTypes.bool.isRequired, - error: PropTypes.object - }, - getInitialState: function() { - return { - newOwner: '' - }; - }, - onChangeOwner: function(e) { - e.preventDefault(); - var newOwner = e.target.value; - this.context.executeAction(updateToOrgOwner, { newOwner: newOwner }); - }, - onCancelClick: function(e) { - e.preventDefault(); - this.props.history.pushState(null, '/account/settings/'); - }, - submitChangeOrg: function(e) { - e.preventDefault(); - debug('Change user to org'); - this.context.executeAction(convertToOrgAction, - {jwt: this.props.JWT, username: this.props.user.username, newOwner: this.props.newOwner}); - }, - render: function() { - var disabled = !this.props.newOwner; - var intent = this.props.convertError ? 'alert' : null; - let error = null; - if (this.props.convertError) { - error = ( -
    - { _.map(this.props.error, _mkErrors) } -
    - ); - } - return ( -
    - -
    -
    - -
    Your user account will be transformed into an organization account where all administrative duties are left to another user or group of users. You will no longer be able to login to this account.
    -
    - -
    Email addresses for this account will be removed, freeing them up to be used for any other accounts.
    -
    - -
    Converting your account removes any associations to other services like GitHub or Atlassian Bitbucket. You will be able to link your external accounts to another Docker Hub user.
    -
    - -
    Billing details and Private Repository plans will remain attached to this account after it is converted to an organization.
    -
    - -
    Repository namespaces and names remain unchanged. Any user collaborators that you have configured for these repositories will be removed and must be reconfigured using group collaborators.
    -
    - -
    Automated Builds for this account will be updated to appear as if they were originallly configured by the initial organization owner. Any user in a group with 'admin' level access to a repository will be able to edit Automated Build Configurations.
    -
    -
    -
    -
    WARNING
    -
    This account conversion operation can not be undone.
    -
    -
    -
    -
    -

    In order to complete the conversion of your account to an organization you will need to enter the Docker ID of an **existing** Docker Hub user account. - The user account you specify will become a member of the Owners group and will have full administrative privileges to manage the organization.

    - - { error } -
    -
    -
    - -
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    - ); - } -}); - -export default connectToStores(ConvertToOrg, - [ConvertToOrgStore], - function({ getStore }, props) { - return getStore(ConvertToOrgStore).getState(); - }); diff --git a/app/scripts/components/account/CreateBillingSubscription.css b/app/scripts/components/account/CreateBillingSubscription.css deleted file mode 100644 index d7d63cbe3e..0000000000 --- a/app/scripts/components/account/CreateBillingSubscription.css +++ /dev/null @@ -1,36 +0,0 @@ -@import "dux/css/box"; -@import 'dux/css/colors.css'; - -.select { - width: 5rem; -} -.error { - color: var(--primary-5); -} - -.title { - font-weight: 700; - margin-top: 1.5rem; -} - -.subtitle { - color: var(--primary-2); - margin-bottom: .5rem; -} - -.preview { - composes: module from 'dux/dux/Module/Module.css'; - padding: 2rem 2rem 0; - margin-left: 1rem; -} - -.total { - margin-bottom: 35px; -} - -.couponCode { - margin-top: 2rem; -} -.price { - text-align: right; -} diff --git a/app/scripts/components/account/CreateBillingSubscription.jsx b/app/scripts/components/account/CreateBillingSubscription.jsx deleted file mode 100644 index 972231444b..0000000000 --- a/app/scripts/components/account/CreateBillingSubscription.jsx +++ /dev/null @@ -1,319 +0,0 @@ -'use strict'; - -import React, { PropTypes } from 'react'; -const { string, number, func, shape, object, array, oneOfType } = PropTypes; -import map from 'lodash/collection/map'; -import find from 'lodash/collection/find'; -import includes from 'lodash/collection/includes'; -import has from 'lodash/object/has'; -import merge from 'lodash/object/merge'; -import classnames from 'classnames'; -import { Link } from 'react-router'; -import connectToStores from 'fluxible-addons-react/connectToStores'; - -import BillingInfoForm from './billingplans/BillingInfoForm.jsx'; -import BillingInfoFormStore from '../../stores/BillingInfoFormStore.js'; -import PlansStore from '../../stores/PlansStore.js'; -import BillingPlansStore from '../../stores/BillingPlansStore.js'; -import DUXInput from '../common/DUXInput.jsx'; -import createBillingSubscription from '../../actions/createSubscription.js'; -import updateSubscriptionPlanOrPackage from '../../actions/updateSubscriptionPlanOrPackage.js'; -import updateBillingInfoFormField from '../../actions/updateBillingInfoFormField.js'; -import validateBillingInfo from '../../actions/common/validateBillingInfo.js'; -import validateCouponCode from '../../actions/validateCouponCode.js'; -import EnterpriseLoggedOutPage from '../enterprise/EnterpriseLoggedOutPage.jsx'; -import { Button, PageHeader } from 'dux'; -import styles from './CreateBillingSubscription.css'; - -var debug = require('debug')('createBillingSubscription'); - -function mkShortPlanIntervalUnit(unit) { - if (unit === 'months'){ - return 'mo'; - } else if (unit === 'years') { - return 'yr'; - } else { - return 'mo'; - } -} - -function _mkOptions(list_item) { - return ( - - ); -} - -var CreateBillingSubscription = React.createClass({ - displayName: 'CreateBillingSubscription', - contextTypes: { - getStore: func.isRequired, - executeAction: func.isRequired - }, - getInitialState: function() { - return { - couponCode: '', - selectedPlan: this.props.location.query.plan - }; - }, - propTypes: { - JWT: string.isRequired, - user: object.isRequired, - billingInfoForm: shape({ - billforwardId: string, - accountInfo: shape({ - account_code: string, - username: string, - email: string, - first_name: string, - last_name: string, - company_name: string - }), - billingInfo: shape({ - city: string, - state: string, - zip: string, - first_name: string, - last_name: string, - address1: string, - address2: string, - country: string - }), - card: shape({ - number: string, - cvv: string, - month: oneOfType([number, string]), - year: oneOfType([number, string]), - type: string, - coupon_code: string, - coupon: number - }), - errorMessage: string, - fieldErrors: object, - STATUS: string - }), - plans: shape({ - currentPlan: shape({ - subscription_uuid: string, - package: string - }), - plansList: array - }) - }, - createBillingSubscription(){ - const { JWT, user } = this.props; - const { billforwardId, accountInfo, billingInfo, card } = this.props.billingInfoForm; - const { currentPlan } = this.props.plans; - const { package: currentPackage, subscription_uuid } = currentPlan; - const { selectedPlan } = this.state; - const { executeAction } = this.context; - if (selectedPlan) { - // User has no billing profile account OR no billing payment information - var subscriptionData = { - JWT, - user, - accountInfo, - billingInfo, - card, - billforwardId, - isNewBillingAccount: accountInfo.newBilling, - plan_code: selectedPlan - }; - - return executeAction(createBillingSubscription, subscriptionData); - } else if (currentPackage) { - // User HAS a CLOUD plan - upgrade to hub plan WITH cloud subscription - // SHOULD NEVER REACH HERE ANYMORE - PACKAGES HAVE BEEN REMOVED!! - const namespace = user.username || user.orgname; - let updatePlanInfo = { - JWT, - username: namespace, - subscription_uuid: subscription_uuid, - plan_code: selectedPlan, - package_code: currentPackage, - coupon_code: card.coupon_code - }; - return executeAction(updateSubscriptionPlanOrPackage, updatePlanInfo); - } - return executeAction(validateBillingInfo({storePrefix: 'BILLING'})); - }, - getPlan(selectedPlan) { - const plans = [ - 'index_personal_micro', - 'index_personal_small', - 'index_personal_medium', - 'index_personal_large', - 'index_personal_xlarge', - 'index_personal_xxlarge' - ]; - if (selectedPlan && includes(plans, selectedPlan)) { - const { plansList } = this.props.plans; - const planObject = find(plansList, {plan_code: selectedPlan}); - const interval = has(planObject, 'plan_interval_unit') ? mkShortPlanIntervalUnit(planObject.plan_interval_unit) : 'mo'; - const price = parseInt(planObject.price_in_cents, 10) / 100; - return {planCode: planObject.plan_code, price: price, interval}; - } else { - return {price: 0, interval: 'mo', planCode: null}; - } - }, - _onChange(field, fieldKey) { - return (e) => { - this.context.executeAction(updateBillingInfoFormField, { - field, - fieldKey, - fieldValue: e.target.value - }); - }; - }, - _updateSelectPlan(e) { - e.preventDefault(); - let planCode = e.target.value; - const { card } = this.props.billingInfoForm; - this.setState({selectedPlan: planCode}); - this.props.history.pushState(null, this.props.location.pathname, {plan: planCode}); - if (card.coupon > 0 || this.state.couponCode) { - this.context.executeAction(validateCouponCode, {coupon_code: this.state.couponCode, plan: planCode}); - } - }, - _updateCoupon(e) { - e.preventDefault(); - this.setState({couponCode: e.target.value}); - }, - validateCoupon(plan) { - return (e) => { - e.preventDefault(); - this.context.executeAction(validateCouponCode, {coupon_code: this.state.couponCode, plan: plan}); - this.setState({couponCode: ''}); - }; - }, - render: function() { - const { plansList } = this.props.plans; - const { selectedPlan } = this.state; - const { JWT, user, history } = this.props; - - if(!JWT) { - //get plan type from end of '?plan=index_personal_PLANTYPE' - //default to micro plan if no query selected - const planType = selectedPlan ? selectedPlan.substring(15) : 'micro'; - return ; - } else { - const { accountInfo, billingInfo, card, fieldErrors, STATUS, errorMessage } = this.props.billingInfoForm; - const { price, interval, planCode } = this.getPlan(selectedPlan); - - var discount; - if (card.coupon > 0) { - discount = '- $' + card.coupon; - } else { - discount = '-----'; - } - let titleClass = classnames({ - [styles.title]: true, - [styles.error]: true - }); - let title = ( -
    - * Please select a plan:  - -
    - ); - - if (selectedPlan) { - title = ( -
    - You are subscribing to the   - -   plan at ${price}/{interval} -
    - ); - } - const namespace = user.username || user.orgname; - const isOrg = !!user.orgname; - - return ( -
    - - -
    -
    - { title } -
    Once your billing information has been processed, your account will be immediately upgraded.
    -
    Thank you for subscribing!
    -
    Your billing information can be updated at any time
    -
    -
    -
    -
    - -
    -
    -
    -
    - Plan Cost: -
    -
    - ${price} -
    -
    -
    -
    - Coupon: -
    -
    - {discount} -
    -
    -
    -
    -
    - Total Charge: -
    -
    - ${price - card.coupon} -
    -
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -
    - ); - } - } -}); - -export default connectToStores(CreateBillingSubscription, - [BillingInfoFormStore, PlansStore], - function({ getStore }, props) { - return merge({}, - {plans: getStore(PlansStore).getState(), billingInfoForm: getStore(BillingInfoFormStore).getState()}); - }); diff --git a/app/scripts/components/account/Licenses.css b/app/scripts/components/account/Licenses.css deleted file mode 100644 index dda5c374ae..0000000000 --- a/app/scripts/components/account/Licenses.css +++ /dev/null @@ -1,51 +0,0 @@ -@import "dux/css/box"; -@import "dux/css/colors"; - -.license { - background: var(--white); - border: 1px solid var(--iron); - border-top-right-radius: var(--global-radius) 0; - border-top-left-radius: var(--global-radius) 0; - padding: 1rem 2rem; - margin: 1rem 0 0 0; -} - -.download { - background: var(--secondary-5); - color: var(--secondary-2); - border-bottom-right-radius: var(--global-radius) 0; - border-bottom-left-radius: var(--global-radius) 0; - text-align: center; - padding: .5rem; - line-height: 16px; - font-size: 14px; -} - -.downloadAlert { - background: var(--alert-color); - color: var(--secondary-5); - border-bottom-right-radius: var(--global-radius) 0; - border-bottom-left-radius: var(--global-radius) 0; - text-align: center; - padding: .5rem; -} - -.pageWrapper { - padding-top: 1.25rem; -} - -.legal { - font-size: 12px; - font-style: italic; - min-height: 48px; -} - -input.checkbox { - margin-bottom: 0; - margin-right: 4px; -} - -.finePrint { - font-size: 10px; - font-style: italic; -} diff --git a/app/scripts/components/account/Licenses.jsx b/app/scripts/components/account/Licenses.jsx deleted file mode 100644 index e7a724d8a7..0000000000 --- a/app/scripts/components/account/Licenses.jsx +++ /dev/null @@ -1,214 +0,0 @@ -'use strict'; - -import React, { PropTypes, createClass, Component } from 'react'; -import _ from 'lodash'; -import moment from 'moment'; -import classnames from 'classnames'; -import { Link } from 'react-router'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import request from 'superagent'; - -// Blob is a polyfill -require('vendor/Blob'); -import { saveAs } from 'vendor/FileSaver'; -import FA from 'common/FontAwesome'; - -import { PageHeader } from 'dux'; -import AccountSettingsLicensesStore from '../../stores/AccountSettingsLicensesStore'; -import Row from '../common/Row'; -import CSEngineBox from 'common/CSEngineBox'; - -import styles from './Licenses.css'; - -var debug = require('debug')('AccountSettingsLicenses'); - -class LicenseBox extends Component { - - state = { - hasAcceptedTerms: false, - hasError: false, - isDownloading: false, - // Paid licenses require terms - // https://github.com/docker/dhe-license-server/blob/master/tiers/tiers.go - requiresAcceptedTerms: this.props.tier !== 'Trial' && this.props.tier !== 'Evaluation' - } - - onCheckboxChange = () => { - this.setState({ - hasAcceptedTerms: !this.state.hasAcceptedTerms - }); - } - - onClick = (e) => { - this.setState({ - isDownloading: true, - hasError: false - }); - request.get(process.env.REGISTRY_API_BASE_URL - + '/api/licensing/v3/license/' - + this.props.orgname - + '/' - + this.props.keyId - + '/') - .set('Authorization', 'JWT ' + this.props.JWT) - .end((err, res) => { - if(err) { - this.setState({ - isDownloading: false, - hasError: true - }); - } else { - - this.setState({ - isDownloading: false, - hasError: false - }); - - const blob = new Blob([res.text], { - type: 'text/plain;charset=utf-8' - }); - saveAs(blob, `docker_subscription.lic`); - } - - }); - } - - render() { - const { expiration, alias, orgname, end, tier, maxEngines } = this.props; - const { requiresAcceptedTerms, hasAcceptedTerms } = this.state; - const exp = moment(expiration).fromNow(); - // This is a temporary work around until we can enable click to accept - // in Store - let maybeTermsAndConditions =
    ; - if (requiresAcceptedTerms) { - const EUSALink = 'https://www.docker.com/docker-software-end-user-subscription-agreement'; - const checkbox = ( - - ); - maybeTermsAndConditions = ( -
    - { checkbox } - I agree to Docker's subscription terms -
    This will not override any pre-negotiated terms.
    -
    - ); - } - - const preventDownload = requiresAcceptedTerms && !hasAcceptedTerms; - let icon; - let onClick; - if (preventDownload) { - icon = 'Please accept terms to download'; - onClick = () => {}; - } else { - icon = ; - onClick = this.onClick; - if(this.state.isDownloading) { - icon = ; - } - } - - const classes = classnames({ - 'large-3 columns': true, - 'end': end - }); - - const downloadClasses = classnames({ - [styles.download]: !this.state.hasError, - [styles.downloadAlert]: this.state.hasError - }); - return ( -
    -
    -

    {alias}

    -

    Organization: {orgname}

    -

    Engines: {maxEngines}

    -

    Expires: {exp}

    - { maybeTermsAndConditions } -
    - -
    {icon}
    -
    - ); - } -} - -class Licenses extends Component { - contextTypes: { - executeAction: React.PropTypes.func.isRequired - } - - propTypes: { - JWT: PropTypes.string.isRequired, - licenses: PropTypes.array.isRequired - } - - state = { - rpm: { - isDownloading: false, - hasError: false - }, - deb: { - isDownloading: false, - hasError: false - } - } - - - render() { - if(this.props.licenses.length <= 0) { - return ( -
    - - -
    You don't seem to have any - licenses; Get a - Trial. -
    -
    -
    - ); - } else { - const { rpm, deb } = this.state; - - const icon = ; - const iconDownloading = ; - - const rpmIcon = rpm.isDownloading ? iconDownloading : icon; - const debIcon = deb.isDownloading ? iconDownloading : icon; - - const rpmIntent = rpm.hasAlert ? 'alert' : null; - const debIntent = deb.hasAlert ? 'alert' : null; - - return ( -
    - -
    -
    -
    - -
    -
    -
    - {this.props.licenses.map((license, i, arr) => { return ; } )} -
    -
    -
    - ); - } - } -} - -export default connectToStores(Licenses, - [ - AccountSettingsLicensesStore - ], - function({ getStore }, props) { - return getStore(AccountSettingsLicensesStore).getState(); - }); diff --git a/app/scripts/components/account/LinkedServices.css b/app/scripts/components/account/LinkedServices.css deleted file mode 100644 index e8b35530b3..0000000000 --- a/app/scripts/components/account/LinkedServices.css +++ /dev/null @@ -1,44 +0,0 @@ -@import 'dux/css/colors.css'; -@import 'dux/css/box.css'; - -.body { - margin-top: 2rem; -} - -.icon { - width: 100px; - height: 100px; -} - -.name { - font-weight: 700; - margin: 0 var(--default-margin); -} - -.access { - margin: .5rem 0; - text-align: left; -} - -.service { - composes: base from 'dux/dux/Module/Module.css'; - color: var(--secondary-4); - padding: 1.8rem; - text-align: center; - transition: border .2s; - i { - font-size: 5rem; - margin-bottom: 1rem; - } - &:hover { - background: #f4f9fc; - color: var(--secondary-4); - cursor: pointer; - } - &.link:hover { - border: 1px solid var(--primary-2); - } - &.unlink:hover { - border: 1px solid var(--primary-5); - } -} \ No newline at end of file diff --git a/app/scripts/components/account/LinkedServices.jsx b/app/scripts/components/account/LinkedServices.jsx deleted file mode 100644 index 4a93cf086e..0000000000 --- a/app/scripts/components/account/LinkedServices.jsx +++ /dev/null @@ -1,174 +0,0 @@ -'use strict'; - -import React, { PropTypes, Component } from 'react'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import { PageHeader } from 'dux'; - -import AutobuildStore from '../../stores/AutobuildStore'; -import BitbucketLinkStore from '../../stores/BitbucketLinkStore'; -import GithubLinkStore from '../../stores/GithubLinkStore'; -import GithubLinkAction from '../../actions/linkGithub'; -import BitbucketLinkAction from '../../actions/linkBitbucket'; -import GithubUnlinkAction from '../../actions/unlinkGithub'; -import BitbucketUnlinkAction from '../../actions/unlinkBitbucket'; -import { Button, Module } from 'dux'; -import { SplitSection } from '../common/Sections.jsx'; -import FA from '../common/FontAwesome'; -import classnames from 'classnames'; -import styles from './LinkedServices.css'; -import merge from 'lodash/object/merge'; - -const { string, array, object, func } = PropTypes; - -class LinkedServices extends Component { - - static contextTypes = { - executeAction: func.isRequired - } - - static propTypes = { - JWT: string.isRequired, - githubAccount: object, - githubRepos: array, - bitbucketAccount: object, - bitbucketRepos: array, - gitlabAccount: object, - gitlabRepos: array, - bitbucketError: string, - bbAuthUrl: string, - githubError: string - } - - authServiceClick = (e) => { - e.preventDefault(); - } - - render() { - var github = {service: 'Github', account: this.props.githubAccount}; - var bitbucket = {service: 'Bitbucket', account: this.props.bitbucketAccount}; - var gitlab = {service: 'Gitlab', account: this.props.gitlabAccount}; - let maybeError; - const errorMsg = this.props.githubError || this.props.bitbucketError; - if (errorMsg) { - maybeError = {errorMsg}; - } - return ( -
    - -
    -
    - - These account links are currently used for Automated Builds, - so that we can access your project lists and help you configure your Automated Builds. -   Please note: A github/bitbucket account can be connected to only one docker hub account at a time.

    }> -
    - - -
    -
    - {maybeError} -
    -
    -
    -
    - ); - } -} - -class LinkedAccount extends Component { - static propTypes = { - data: object, - bbAuthUrl: string, - JWT: string, - history: object.isRequired - } - - static contextTypes = { - executeAction: PropTypes.func.isRequired - } - - linkAction = (provider, e) => { - e.preventDefault(); - if (provider.service.toLowerCase() === 'github') { - this.context.executeAction(GithubLinkAction, this.props.JWT); - this.props.history.pushState(null, '/account/authorized-services/github-permissions/'); - } else if (provider.service.toLowerCase() === 'bitbucket') { - const bbWin = window.open(); - bbWin.location = this.props.bbAuthUrl; - } - } - - unlinkAction = (provider, e) => { - e.preventDefault(); - if (provider.service.toLowerCase() === 'github') { - this.context.executeAction(GithubUnlinkAction, this.props.JWT); - } else if (provider.service.toLowerCase() === 'bitbucket') { - this.context.executeAction(BitbucketUnlinkAction, this.props.JWT); - } - } - - render() { - var service = this.props.data.service; - var icon; - if (service.toLowerCase() === 'github') { - icon = 'fa-github'; - } else if (service.toLowerCase() === 'bitbucket') { - icon = 'fa-bitbucket'; - } - var account = this.props.data.account; - let linkClass = classnames({ - [styles.service]: true, - [styles.unlink]: account, - [styles.link]: !account - }); - if (account) { - return ( -
    -
    -
    -
    - -
    -
    - {account.login}:
    - read/write access -
    -

    - Unlink {service} -
    -
    - ); - } else { - return ( -
    -
    -
    - Link {service} -
    -
    - ); - } - } -} - -export default connectToStores(LinkedServices, - [ - AutobuildStore, - BitbucketLinkStore, - GithubLinkStore - ], - function({ getStore }, props) { - return merge( - {}, - getStore(AutobuildStore).getState(), - { bitbucketError: getStore(BitbucketLinkStore).getState().error, - bbAuthUrl: getStore(BitbucketLinkStore).getState().authURL, - githubError: getStore(GithubLinkStore).getState().error } - ); - }); diff --git a/app/scripts/components/account/NotificationsSettings.css b/app/scripts/components/account/NotificationsSettings.css deleted file mode 100644 index 1a3cebfd7a..0000000000 --- a/app/scripts/components/account/NotificationsSettings.css +++ /dev/null @@ -1,36 +0,0 @@ -@import 'dux/css/colors.css'; - -.body { - margin-top: 2rem; -} - -.button { - margin-bottom: -1rem; -} - -.success { - border: 1px solid var(--primary-2); -} - -.formError { - border: 1px solid var(--primary-5); -} - -.notification { - margin-bottom: 1rem; - word-wrap: break-word; -} -.notification:hover { - cursor: pointer; - cursor: hand; -} -.unverifiedNotif { - margin-bottom: 1rem; - word-wrap: break-word; - color: var(--secondary-4); - cursor: default; -} - -.checkbox { - padding-top: .5rem; -} diff --git a/app/scripts/components/account/NotificationsSettings.jsx b/app/scripts/components/account/NotificationsSettings.jsx deleted file mode 100644 index f0fdfc0046..0000000000 --- a/app/scripts/components/account/NotificationsSettings.jsx +++ /dev/null @@ -1,236 +0,0 @@ -'use strict'; - -import React, { PropTypes } from 'react'; -import _ from 'lodash'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import classnames from 'classnames'; - -import { Button, PageHeader } from 'dux'; -import OutboundCommunicationStore from '../../stores/OutboundCommunicationStore'; -import EmailsStore from '../../stores/EmailsStore'; -import resetNotifications from '../../actions/resetNotifications.js'; -import saveOutbound from '../../actions/saveOutbound'; -import UpdateOutbound from '../../actions/updateOutbound.js'; -import EmailNotifForm from './notificationSettings/EmailNotifForm.jsx'; -var debug = require('debug')('NotificationSettings'); - -import { SplitSection } from './../common/Sections.jsx'; -import styles from './NotificationsSettings.css'; - -var Notifications = React.createClass({ - displayName: 'Notifications', - contextTypes: { - executeAction: PropTypes.func.isRequired - }, - propTypes: { - user: PropTypes.shape({ - username: PropTypes.string - }), - JWT: PropTypes.string - }, - getDefaultProps: function() { - return { - user: {}, - JWT: '' - }; - }, - onOutboundClick: function(e) { - debug('onOutboundClick'); - var email = e.currentTarget.getAttribute('data-email'); - var list = e.currentTarget.getAttribute('data-list'); - var unsubscribedIndex; - var subscribedIndex; - var newSubscribed; - var newUnsubscribed; - var newList; - if (list === 'weekly') { - /*eslint-disable camelcase */ - unsubscribedIndex = this.props.weeklyDigest.unsubscribed_emails.indexOf(email); - subscribedIndex = this.props.weeklyDigest.subscribed_emails.indexOf(email); - newUnsubscribed = _.clone(this.props.weeklyDigest.unsubscribed_emails); - newSubscribed = _.clone(this.props.weeklyDigest.subscribed_emails); - if (unsubscribedIndex > -1 && subscribedIndex === -1) { - newUnsubscribed.splice(unsubscribedIndex, 1); - newSubscribed.push(email); - } else { - newSubscribed.splice(subscribedIndex, 1); - newUnsubscribed.push(email); - } - newList = { - subscribed_emails: newSubscribed, - unsubscribed_emails: newUnsubscribed - }; - this.context.executeAction(UpdateOutbound, {list: 'weekly', data: newList}); - /*eslint-enable camelcase */ - } else if (list === 'beta') { - unsubscribedIndex = this.props.betaGroup.unsubscribed_emails.indexOf(email); - subscribedIndex = this.props.betaGroup.subscribed_emails.indexOf(email); - newUnsubscribed = _.clone(this.props.betaGroup.unsubscribed_emails); - newSubscribed = _.clone(this.props.betaGroup.subscribed_emails); - if (unsubscribedIndex > -1 && subscribedIndex === -1) { - newUnsubscribed.splice(unsubscribedIndex, 1); - newSubscribed.push(email); - } else { - newSubscribed.splice(subscribedIndex, 1); - newUnsubscribed.push(email); - } - newList = { - unsubscribed_emails: newUnsubscribed, - subscribed_emails: newSubscribed - }; - this.context.executeAction(UpdateOutbound, {list: 'beta', data: newList}); - } - }, - onOutboundSubmit: function(e) { - e.preventDefault(); - let _this = this; - let weeklyUns = []; - let betaUns = []; - let weekly = _.clone(this.props.weeklyDigest); - let beta = _.clone(this.props.betaGroup); - /* eslint-disable camelcase */ - weekly.unsubscribed_emails.forEach(function(email) { - if (_this.isVerified(email)) { - weeklyUns.push(email); - } - }); - weekly.unsubscribed_emails = weeklyUns; - beta.unsubscribed_emails.forEach(function(email) { - if (_this.isVerified(email)) { - betaUns.push(email); - } - }); - beta.unsubscribed_emails = betaUns; - /* eslint-enable camelcase */ - var outboundData = { - JWT: this.props.JWT, - username: this.props.user.username, - weeklyDigest: weekly, - betaGroup: beta - }; - this.context.executeAction(saveOutbound, outboundData); - }, - onOutboundCancel: function(e) { - debug('resetting outbound communication'); - this.context.executeAction(resetNotifications, ['outbound']); - }, - sortEmails: function(emailArray) { - var _this = this; - return (_.sortBy(emailArray, - function(email) { - return !(_this.isVerified(email)); - }) - ); - }, - isVerified: function(email) { - return _.pluck(_.filter(this.props.emails, {email: email}), 'verified')[0]; - }, - render: function() { - var digestEmails = this.sortEmails(this.props.digestEmails); - var betaEmails = this.sortEmails(this.props.betaEmails); - return ( -
    - -
    -
    - - - The following settings will control how Docker communicates news, new products, new features, and more.

    }> -
    - -
    Docker Weekly
    -

    Docker weekly is a newsletter which contains the latest news, updates, and information on releases and other exciting stuff. Sign up!

    -
    - -
    Docker Beta Group
    -

    Become part of our Docker Beta Group and get early access to some Docker products and/or features.

    -

    Please select which email address (or addresses) you'd like to subscribe:

    -
    - -
    -
    - -
    -
    - -
    -
    -
    -
    - -
    -
    -
    - ); - } -}); - -var OutboundList = React.createClass({ - contextTypes: { - executeAction: PropTypes.func.isRequired - }, - propTypes: { - emailGroups: PropTypes.shape({ - subscribed_emails: PropTypes.array, - unsubscribed_emails: PropTypes.array - }), - emailList: PropTypes.array, - emails: PropTypes.array, - onOutboundClick: PropTypes.func.isRequired, - type: PropTypes.string.isRequired - }, - render: function() { - let _this = this; - return ( -
    -
    -
    - {this.props.children} -
    -
    - {this.props.emailList.map(function(email) { - if (_this.props.isVerified(email)) { - return ( -
    -
    - -
    -
    - {email} -
    -
    - ); - } else { - return ( -
    -
    - -
    -
    - {email} - unverified -
    -
    - ); - } - })} -
    - ); - } -}); - -export default connectToStores(Notifications, - [OutboundCommunicationStore, EmailsStore], function({ getStore }, props) { - return _.merge({}, getStore(OutboundCommunicationStore).getState(), getStore(EmailsStore).getEmails()); - }); diff --git a/app/scripts/components/account/OrganizationSettings.jsx b/app/scripts/components/account/OrganizationSettings.jsx deleted file mode 100644 index 592cbcaef0..0000000000 --- a/app/scripts/components/account/OrganizationSettings.jsx +++ /dev/null @@ -1,59 +0,0 @@ -'use strict'; - -import React, { cloneElement } from 'react'; -import { Link } from 'react-router'; -import FluxibleMixin from 'fluxible-addons-react/FluxibleMixin'; -import OrganizationStore from '../../stores/OrganizationStore'; -import { PageHeader } from 'dux'; -import FA from '../common/FontAwesome'; -const debug = require('debug')('OrganizationSettings'); - -var OrganizationSettings = React.createClass({ - displayName: 'OrganizationSettings', - mixins: [FluxibleMixin], - getInitialState: function() { - return { - orgs: this.context.getStore(OrganizationStore).getOrgs() - }; - }, - statics: { - storeListeners: { - onOrgStoreChange: [OrganizationStore] - } - }, - onOrgStoreChange: function() { - this.setState({ - orgs: this.context.getStore(OrganizationStore).getOrgs() - }); - }, - componentDidMount: function() { - this.setState({ - orgs: this.context.getStore(OrganizationStore).getOrgs() - }); - }, - render: function() { - - var maybeCreateOrgBtn; - var pathname = this.props.location.pathname; - if (pathname.indexOf('/add/') === -1) { - maybeCreateOrgBtn = Create Organization ; - } - - return ( -
    - - {maybeCreateOrgBtn} - -
    - {cloneElement(this.props.children, { - user: this.props.user, - JWT: this.props.JWT, - orgs: this.state.orgs - })} -
    -
    - ); - } -}); - -module.exports = OrganizationSettings; diff --git a/app/scripts/components/account/OrganizationSummary.css b/app/scripts/components/account/OrganizationSummary.css deleted file mode 100644 index 65001dbfb0..0000000000 --- a/app/scripts/components/account/OrganizationSummary.css +++ /dev/null @@ -1,23 +0,0 @@ -@import "dux/css/box.css"; - -.orgGridItem { - composes: module from "dux/dux/Module/Module.css"; - text-align: center; - &:hover { - cursor: pointer; - } -} -.orgSummary { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} -.orgAvatar { - width: 3rem; - height: 3rem; - border-radius: 100%; - padding: 5px; -} -.orgListItem { - list-style: none; -} diff --git a/app/scripts/components/account/OrganizationSummary.jsx b/app/scripts/components/account/OrganizationSummary.jsx deleted file mode 100644 index 554dbbca17..0000000000 --- a/app/scripts/components/account/OrganizationSummary.jsx +++ /dev/null @@ -1,62 +0,0 @@ -'use strict'; - -import styles from './OrganizationSummary.css'; -import classnames from 'classnames'; -import React, { Component, PropTypes } from 'react'; -const { bool, string } = PropTypes; -import { Link } from 'react-router'; -import selectOrganizationAction from '../../actions/selectOrganization'; -import { mkAvatarForNamespace } from 'utils/avatar'; - -const debug = require('debug')('OrganizationSummary'); - - -class OrgItem extends Component { - - static propTypes = { - orgname: string.isRequired, - end: bool - } - - render() { - const { orgname, end } = this.props; - const classes = classnames( - styles.orgListItem, - 'medium-3', - 'columns', - { - 'end': end - } - ); - return ( -
  • - -
    - -
    {orgname}
    -
    - -
  • - ); - } -} - -export default class OrganizationSummary extends Component { - static contextTypes = { - executeAction: React.PropTypes.func.isRequired - } - static propTypes = { - user: React.PropTypes.object.isRequired, - JWT: React.PropTypes.string.isRequired, - orgs: React.PropTypes.array.isRequired - } - render() { - const orgItems = this.props.orgs.map((org, i, array) => { return ; }); - - return ( -
      - {orgItems} -
    - ); - } -} diff --git a/app/scripts/components/account/UpdateBillingInfo.css b/app/scripts/components/account/UpdateBillingInfo.css deleted file mode 100644 index b2ee158666..0000000000 --- a/app/scripts/components/account/UpdateBillingInfo.css +++ /dev/null @@ -1,11 +0,0 @@ -@import "dux/css/box"; -@import "dux/css/colors"; - -.body { - margin-top: var(--default-margin); -} - -.subtitle { - color: var(--primary-2); - margin-bottom: .5rem; -} diff --git a/app/scripts/components/account/UpdateBillingInfo.jsx b/app/scripts/components/account/UpdateBillingInfo.jsx deleted file mode 100644 index 1b7baf22e2..0000000000 --- a/app/scripts/components/account/UpdateBillingInfo.jsx +++ /dev/null @@ -1,131 +0,0 @@ -'use strict'; -import React, { PropTypes } from 'react'; -const { string, number, func, shape, object, array, oneOfType } = PropTypes; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import updateBillingInformation from '../../actions/updateBillingInformation.js'; -import updateStripeBilling from '../../actions/updateStripeBilling.js'; -import BillingInfoFormStore from '../../stores/BillingInfoFormStore.js'; -import BillingInfoForm from './billingplans/BillingInfoForm.jsx'; -import { Link } from 'react-router'; -import classnames from 'classnames'; -import styles from './UpdateBillingInfo.css'; -import { PageHeader, Module } from 'dux'; -var debug = require('debug')('UpdateBillingInfo:'); - -var updateBillingInfoPage = React.createClass({ - displayName: 'UpdateBillingInfo', - contextTypes: { - getStore: func.isRequired, - executeAction: func.isRequired - }, - propTypes: { - JWT: string.isRequired, - user: object.isRequired, - billforwardId: string, - accountInfo: shape({ - account_code: string, - username: string, - email: string, - first_name: string, - last_name: string, - company_name: string - }), - billingInfo: shape({ - city: string, - state: string, - zip: string, - first_name: string, - last_name: string, - address1: string, - address2: string, - country: string - }), - card: shape({ - number: string, - cvv: string, - month: oneOfType([number, string]), - year: oneOfType([number, string]), - type: string - }), - errorMessage: string, - fieldErrors: object, - STATUS: string - }, - updateBillingInfoSubmit(){ - const { - JWT, - user, - accountInfo, - billingInfo, - card, - billforwardId, - location - } = this.props; - if (billforwardId) { - // If we have a billforwardID then we will update via stripe - this.context.executeAction(updateStripeBilling, { - JWT, - user, - accountInfo, - billingInfo, - billforwardId, - card - }); - } else { - // If we do not have a billforward ID then we go through the original recurly update flow - this.context.executeAction(updateBillingInformation, { - JWT, - user, - accountInfo, - billingInfo, - card - }); - } - }, - render: function() { - const { - user, - history, - accountInfo, - billingInfo, - card, - fieldErrors, - STATUS, - errorMessage - } = this.props; - const namespace = user.username || user.orgname; - let isOrg = !!user.orgname; - return ( -
    - -
    -
    -
    Billing information is required for changing or upgrading subscriptions
    -
    You may update your billing information at any time
    -
    -
    -
    -
    - -
    -
    -
    - ); - } -}); - -export default connectToStores(updateBillingInfoPage, - [BillingInfoFormStore], - function({ getStore }, props) { - return getStore(BillingInfoFormStore).getState(); - }); diff --git a/app/scripts/components/account/billingplans/BillingInfo.css b/app/scripts/components/account/billingplans/BillingInfo.css deleted file mode 100644 index 246b626169..0000000000 --- a/app/scripts/components/account/billingplans/BillingInfo.css +++ /dev/null @@ -1,7 +0,0 @@ -@import 'dux/css/colors.css'; - -.infoContent { - border-left: 1px solid var(--iron); - padding: 0 3rem; - margin: .5rem 0; -} diff --git a/app/scripts/components/account/billingplans/BillingInfo.jsx b/app/scripts/components/account/billingplans/BillingInfo.jsx deleted file mode 100644 index 5b5f210f25..0000000000 --- a/app/scripts/components/account/billingplans/BillingInfo.jsx +++ /dev/null @@ -1,132 +0,0 @@ -'use strict'; - -import React, { PropTypes } from 'react'; -import { Link } from 'react-router'; - -import Button from '@dux/element-button'; -import { SplitSection } from '../../common/Sections.jsx'; -import FA from '../../common/FontAwesome.jsx'; -import styles from './BillingInfo.css'; - -var BillingInfo = React.createClass({ - propTypes: { - currentPlan: PropTypes.shape({ - id: PropTypes.string, - plan: PropTypes.string - }), - accountInfo: PropTypes.shape({ - account_code: PropTypes.string, - username: PropTypes.string, - email: PropTypes.string, - first_name: PropTypes.string, - last_name: PropTypes.string, - company_name: PropTypes.string - }), - billingInfo: PropTypes.shape({ - city: PropTypes.string, - state: PropTypes.string, - zip: PropTypes.string, - first_name: PropTypes.string, - last_name: PropTypes.string, - address1: PropTypes.string, - address2: PropTypes.string, - country: PropTypes.string - }), - invoices: PropTypes.array, - isOrg: PropTypes.bool.isRequired, - username: PropTypes.string.isRequired - }, - _updateClick: function(e) { - e.preventDefault(); - if (this.props.isOrg) { - this.props.history.pushState(null, `/u/${this.props.username}/dashboard/billing/update-info/`); - } else { - this.props.history.pushState(null, '/account/billing-plans/update/'); - } - }, - render: function() { - const { - accountInfo, - billingInfo, - currentPlan - } = this.props; - if (accountInfo.newBilling) { - return ( -
    - ); - } - let subtitle = ( -
    -
    -

    * fields required to complete a billing transaction

    -
    -
    -
    - -
    -
    -
    - ); - let cardInfo; - if (billingInfo.card_type && billingInfo.last_four) { - cardInfo = ( -
    -
    Card Info:
    -
    - {billingInfo.first_name} {billingInfo.last_name}
    - {billingInfo.card_type} card ending with x{billingInfo.last_four}
    - Expiration: {billingInfo.month}/{billingInfo.year} -
    -
    - ); - } - let addressInfo; - if (billingInfo.address1 && billingInfo.country) { - addressInfo = ( -
    -
    Billing Address:
    -
    - {billingInfo.address1}
    - {billingInfo.address2}
    - {billingInfo.city} {billingInfo.state} {billingInfo.zip}
    - {billingInfo.country} -
    -
    - ); - } - return ( - -
    -
    -
    Name:
    -
    -
    -
    {accountInfo.first_name} {accountInfo.last_name}
    -
    -
    -
    -
    -
    Email:
    -
    -
    -
    {accountInfo.email}
    -
    -
    -
    -
    -
    Company:
    -
    -
    -
    {accountInfo.company_name}
    -
    -
    - { cardInfo } - { addressInfo } -
    - ); - } -}); - -module.exports = BillingInfo; diff --git a/app/scripts/components/account/billingplans/BillingInfoForm.css b/app/scripts/components/account/billingplans/BillingInfoForm.css deleted file mode 100644 index 07b96a3836..0000000000 --- a/app/scripts/components/account/billingplans/BillingInfoForm.css +++ /dev/null @@ -1,36 +0,0 @@ -@import 'dux/css/colors.css'; -@import 'dux/css/box.css'; - -.marginBottom { - margin-bottom: var(--default-margin); -} - -.form { - padding: 0 var(--default-margin); -} - -.billingDropdown { - width: 100%; - margin-bottom: 1.5rem; -} - -.error { - border: 1px solid var(--primary-5); -} - -.billingFormSection { - margin-bottom: 1.5rem; -} - -.dateText { - text-align: center; - height: 2rem; - display: flex; - align-items: center; - margin-bottom: 2rem; -} - -.globalError { - color: var(--primary-5); - padding-bottom: 1rem; -} \ No newline at end of file diff --git a/app/scripts/components/account/billingplans/BillingInfoForm.jsx b/app/scripts/components/account/billingplans/BillingInfoForm.jsx deleted file mode 100644 index 80fb22eb19..0000000000 --- a/app/scripts/components/account/billingplans/BillingInfoForm.jsx +++ /dev/null @@ -1,380 +0,0 @@ -'use strict'; - -import React, { PropTypes } from 'react'; -const { string, number, object, bool, func, shape, oneOfType } = PropTypes; -import { Link } from 'react-router'; -import includes from 'lodash/collection/includes'; -import map from 'lodash/collection/map'; -import classnames from 'classnames'; - -import DUXInput from '../../common/DUXInput.jsx'; -import FA from '../../common/FontAwesome.jsx'; -import acceptedCards from '../../common/data/acceptedCards.js'; -import updateBillingInfoFormField from '../../../actions/updateBillingInfoFormField.js'; -import validateBillingInfo from '../../../actions/common/validateBillingInfo.js'; -import { STATUS } from 'stores/billingformstore/Constants.js'; -import { Button } from 'dux'; -import Card, { Block } from '@dux/element-card'; - -var countries = require('common/data/countries.js'); -var states = require('common/data/states.js'); -var months = require('common/data/months.js'); -var years = require('common/data/years.js'); - -import styles from './BillingInfoForm.css'; -var debug = require('debug')('BillingInfoForm:'); - -var _mkOptions = function(list_item){ - return ( - - ); -}; - -var _mkCountryOptions = function(country) { - return ( - - ); -}; - -var BillingInfoForm = React.createClass({ - contextTypes: { - getStore: func.isRequired, - executeAction: func.isRequired - }, - propTypes: { - isOrg: bool.isRequired, - username: string.isRequired, - accountInfo: shape({ - account_code: string, - username: string, - email: string, - first_name: string, - last_name: string, - company_name: string - }), - billingInfo: shape({ - city: string, - state: string, - zip: string, - first_name: string, - last_name: string, - address1: string, - address2: string, - country: string - }), - card: shape({ - number: string, - cvv: string, - month: oneOfType([number, string]), - year: oneOfType([number, string]), - type: string - }), - fieldErrors: object.isRequired, - errorMessage: string, - STATUS: string.isRequired, - history: object.isRequired - }, - _onChange(field, fieldKey) { - return (e) => { - this.context.executeAction(updateBillingInfoFormField, { - field, - fieldKey, - fieldValue: e.target.value - }); - }; - }, - _onSelectChange(field, fieldKey) { - return (e) => { - var fieldValue = e.target.options[e.target.selectedIndex].value; - if (fieldKey === 'month' || fieldKey === 'year') { - fieldValue = parseInt(fieldValue, 10); - } - this.context.executeAction(updateBillingInfoFormField, { - field, - fieldKey, - fieldValue: fieldValue - }); - }; - }, - _onBackClick(e) { - e.preventDefault(); - if (this.props.isOrg) { - this.props.history.pushState(null, `/u/${this.props.username}/dashboard/billing/`); - } else { - this.props.history.pushState(null, '/account/billing-plans/'); - } - }, - _mkIconFromCardType(cardType) { - const icon = acceptedCards[cardType]; - if (icon) { - return (); - } - }, - formSubmit(e){ - e.preventDefault(); - const billing = this.props.billingInfo; - let validate = window.recurly.validate; - const fieldErrors = { - number: !validate.cardNumber(this.props.card.number), - expiry: !validate.expiry(this.props.card.month, this.props.card.year), - cvv: !validate.cvv(this.props.card.cvv), - first_name: !billing.first_name, - last_name: !billing.last_name, - city: !billing.city, - address1: !billing.address1, - country: !billing.country - }; - const accountErr = { hasError: !this.props.accountInfo.email }; - if (includes(fieldErrors, true) || accountErr.hasError ) { - const hasError = { fieldErrors, accountErr }; - this.context.executeAction(validateBillingInfo({storePrefix: 'BILLING'}), hasError); - } else { - this.props.submitAction(); - } - }, - render: function() { - const { card } = this.props; - const cardIcon = card.number ? this._mkIconFromCardType(card.type) : null; - var expiryClass = classnames({ - [styles.error]: this.props.fieldErrors.expiry, - [styles.billingDropdown]: true - }); - var countryClass = classnames({ - [styles.billingDropdown]: true, - [styles.error]: this.props.fieldErrors.country - }); - let submit = 'Submit'; - if (this.props.STATUS === STATUS.ATTEMPTING) { - submit = ( -
    - Submitting -
    - ); - } - var intent; - if (this.props.STATUS === STATUS.SUCCESS) { - intent = 'success'; - submit = ( -
    - Redirecting -
    - ); - } else if (this.props.STATUS === STATUS.FORM_ERROR) { - intent = 'alert'; - } - const submitButton = ( - - ); - return ( - - -
    -
    -
    Contact Info:
    -
    -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    -
    -
    Billing Info:
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    - -
    -
    - -
    -
    - {cardIcon} -
    -
    -
    -
    - Expires -
    -
    - -
    -
    - / -
    -
    - -
    -
    -
    -
    - -
    -
    - -
    -
    - -
    -
    -
    -
    - -
    -
    - -
    -
    -
    - { this.props.errorMessage } -
    -
    -
    - { submitButton } -
    -
    - -
    -
    -
    -
    -
    - ); - } -}); - -var PostalComponent = React.createClass({ - propTypes: { - billingInfo: shape({ - city: string, - state: string, - zip: string, - first_name: string, - last_name: string, - address1: string, - address2: string, - country: string - }), - onChange: func.isRequired, - onSelectChange: func.isRequired - }, - render: function() { - var countryState; - var country = this.props.billingInfo.country; - var stateClass = this.props.fieldErrors.state ? 'billing-dropdown error' : 'billing-dropdown'; - //IF US TERRITORY - ADD STATES SELECT - if (includes(['US', 'UM'], country)) { - countryState = ( -
    - -
    - ); - } else { - countryState = ( -
    - -
    - ); - } - return ( -
    - {countryState} -
    - -
    -
    - ); - } -}); - -export default BillingInfoForm; diff --git a/app/scripts/components/account/billingplans/EnterpriseSubscriptions.css b/app/scripts/components/account/billingplans/EnterpriseSubscriptions.css deleted file mode 100644 index 0dffb51685..0000000000 --- a/app/scripts/components/account/billingplans/EnterpriseSubscriptions.css +++ /dev/null @@ -1,98 +0,0 @@ -@import 'dux/css/colors.css'; -@import 'dux/css/box.css'; - -.cancel { - float: right; - color: var(--primary-5); -} -.cancel:hover { - color: color(var(--primary-5) blackness(15%)); -} - -.title { - color: var(--primary-1); - i { - color: var(--secondary-5); - } -} -.title:hover { - cursor: pointer; - color: color(var(--primary-1) blackness(55%)); - i { - color: color(var(--secondary-5) blackness(55%)); - } -} - -.cloudStarter { - margin-left: var(--default-margin); -} - -.centerText { - text-align: center; -} - -.check { - color: var(--primary-2); -} - -.download { - margin-right: var(--default-margin);; -} - -.curlHelp { - font-size: .875rem; - font-weight: 500; - margin-bottom: 1rem; -} - -.curlWrap { - width: 100%; -} - -.curlCommand { - resize: none; - overflow: hidden; - height: inherit; -} - -.clipboard { - height: 3rem; - display:flex; - flex-direction: row; - align-items: center; -} - -.downloadFlexItem { - display: flex; - flex-flow: row nowrap; - flex-grow: 4; - flex-basis: 0; - padding: 0 1rem; - word-break: break-word; - max-width: 100%; -} - -.flexbox { - display: flex; - flex-flow: column; -} - -.flexRow { - min-height: 9rem; - padding: 1rem; - display: flex; - align-items: center; - background-color: var(--white); - border: 1px solid var(--secondary-5); - border-radius: 3px; - margin-bottom: .5rem; -} - -.flexItem { - display: flex; - flex-flow: row nowrap; - flex-grow: 1; - flex-basis: 0; - padding: 0.7em 1rem 0.7em 1rem; - word-break: break-word; -} diff --git a/app/scripts/components/account/billingplans/EnterpriseSubscriptions.jsx b/app/scripts/components/account/billingplans/EnterpriseSubscriptions.jsx deleted file mode 100644 index 8e9710c501..0000000000 --- a/app/scripts/components/account/billingplans/EnterpriseSubscriptions.jsx +++ /dev/null @@ -1,160 +0,0 @@ -'use strict'; - -import React, { PropTypes } from 'react'; -const { string, shape, object, func } = PropTypes; -import { Link } from 'react-router'; -import { FullSection } from '../../common/Sections.jsx'; -import FA from '../../common/FontAwesome'; -import styles from './EnterpriseSubscriptions.css'; -import CopyCodeBox from 'common/CopyCodeBox'; -import classnames from 'classnames'; -import {DEB, RPM} from 'common/data/csEngineInstructions'; -const debug = require('debug')('EnterpriseSubscriptions'); - -var EnterpriseSubscriptions = React.createClass({ - propTypes: { - currentPlan: shape({ - id: string, - plan: string - }), - stopSubscription: func.isRequired, - unsubscribing: string, - user: object, - history: object.isRequired - }, - getInitialState() { - return { - confirmAction: '' - }; - }, - selectAction(plan) { - return (e) => { - e.preventDefault(); - this.setState({confirmAction: plan}); - }; - }, - cancelSelectPlan: function(e) { - e.preventDefault(); - this.setState({confirmAction: ''}); - }, - moreInfo: function(e) { - e.preventDefault(); - this.props.history.pushState(null, '/enterprise/'); - }, - purchaseCloud: function(e) { - e.preventDefault(); - this.props.history.pushState(null, '/enterprise/cloud-starter/'); - }, - render: function() { - let owned; - let price; - let subInfo; - let cloudActionButton; - let curlBody; - - // Hide Cloud Starter for anyone who has not already purchased it - if (this.props.currentPlan.package !== 'cloud_starter') { - return null; - } - - owned = ( -
    Currently Subscribed 
    - ); - if (this.state.confirmAction === 'cloud') { - cloudActionButton = ( -
    - Confirm or  - Cancel -
    - ); - } else { - cloudActionButton = ( - - ); - } - if (this.props.unsubscribing === 'package' || this.props.unsubscribing === 'subscription') { - cloudActionButton = (
    Removing Subscription
    ); - } - - let cloudStarter = ( -
    -
    -

     Cloud Starter

    - {owned} -
    -
    - ); - - if (this.state.confirmAction === 'download') { - cloudActionButton = null; - cloudStarter = null; - curlBody = ( -
    -
    -
    -
    - * Copy and run either the RPM or the DEB specific instructions in your terminal. - -
    -
    -
    -
    - RPM - -
    -
    -
    -
    - DEB - - - - For more details about this installation,  - - view our documentation - - -
    -
    -
    -
    - ); - } else { - price = ( -
    $150/mo
    - ); - subInfo = ( -
    -
    - 20 Private Repositories
    - 10 Docker Engines
    - Email Support -
    -
    - ); - } - return ( - -
    -
    - {cloudStarter} - {price} - {subInfo} - {cloudActionButton} - {curlBody} -
    -
    -
    - ); - } -}); - -module.exports = EnterpriseSubscriptions; diff --git a/app/scripts/components/account/billingplans/InvoiceTables.jsx b/app/scripts/components/account/billingplans/InvoiceTables.jsx deleted file mode 100644 index fab6841bda..0000000000 --- a/app/scripts/components/account/billingplans/InvoiceTables.jsx +++ /dev/null @@ -1,73 +0,0 @@ -'use strict'; -import React, { PropTypes } from 'react'; -import { Link } from 'react-router'; -import _ from 'lodash'; -import moment from 'moment'; -import { FullSection } from '../../common/Sections.jsx'; -import { FlexTable, FlexRow, FlexHeader, FlexItem } from '../../common/FlexTable.jsx'; -import downloadInvoice from '../../../actions/downloadInvoice.js'; -const debug = require('debug')('COMPONENT:INVOICE_TABLE'); - -let mkInvoiceTable = function(invoice) { - var subtotal = '$' + (parseInt(invoice.subtotal_in_cents, 10) / 100); - var total = '$' + (parseInt(invoice.total_in_cents, 10) / 100); - var date = moment.utc(invoice.created_at).format('MMM Do YYYY'); - debug('CREATED_AT: ', invoice.created_at); - debug('CREATED_AT_MOMENT: ', date); - return ( - - {date} - {invoice.invoice_number} - {invoice.state} - {total} - - Download Invoice - - - ); -}; - -var InvoiceTables = React.createClass({ - contextTypes: { - executeAction: React.PropTypes.func.isRequired - }, - propTypes: { - invoices: PropTypes.array, - username: PropTypes.string, - JWT: PropTypes.string - }, - downloadInvoice(id) { - return (e) => { - e.preventDefault(); - this.context.executeAction(downloadInvoice, {JWT: this.props.JWT, username: this.props.username, invoiceId: id}); - }; - }, - render: function() { - if (!this.props.JWT || _.isEmpty(this.props.invoices)) { - return ( -
    - ); - } else { - return ( - -
    - - - Date - Invoice # - State - Total - Download - - {this.props.invoices.map(mkInvoiceTable, this)} - -
    -
    - ); - } - } -}); - -module.exports = InvoiceTables; diff --git a/app/scripts/components/account/billingplans/Plans.css b/app/scripts/components/account/billingplans/Plans.css deleted file mode 100644 index 700f88f13b..0000000000 --- a/app/scripts/components/account/billingplans/Plans.css +++ /dev/null @@ -1,58 +0,0 @@ -@import 'dux/css/colors.css'; -@import 'dux/css/box.css'; - -.cancel { - color: var(--primary-5); -} -.cancel:hover { - color: color(var(--primary-5) blackness(15%)); -} - -.shield { - margin-right: 0.5rem; -} - -.nautilusUpsellRow { - display: flex; - width: 100%; - padding: 0.3rem; - background: #f1f6fb; -} - -.nautilusUpsell { - width: 100%; - margin: 0.75rem; - background: var(--white); - border: 1px solid var(--secondary-5); - border-radius: var(--global-radius); - - label { - display: flex; - align-items: center; - padding: 0.5rem; - font-size: 1rem; - font-weight: 400; - line-height: 1rem; - color: var(--secondary-2); - } -} - -.nautilusEnabled { - border-color: #22b8eb; -} - -.enableNautilus { - display: flex; - align-items: center; - margin: 0 0.5rem; - - input { - margin: 0; - } -} - -.monitoredWithNautilus { - display: flex; - align-items: center; - margin: 0.5rem; -} diff --git a/app/scripts/components/account/billingplans/Plans.jsx b/app/scripts/components/account/billingplans/Plans.jsx deleted file mode 100644 index 72d6ef7eb4..0000000000 --- a/app/scripts/components/account/billingplans/Plans.jsx +++ /dev/null @@ -1,355 +0,0 @@ -'use strict'; -/*eslint-disable camelcase*/ -import React, { PropTypes } from 'react'; -import { Link } from 'react-router'; -import PlansStore from '../../../stores/PlansStore'; -import updateSubscriptionPlanOrPackage from '../../../actions/updateSubscriptionPlanOrPackage.js'; -import defaultPlans from 'common/data/plans.js'; -/** -* Used for the public pricing page (/billing-plans/) -* We should either find a workaround for defaultPlans or remove this route altogether -*/ -import FA from '../../common/FontAwesome.jsx'; -import _ from 'lodash'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import { FullSection } from '../../common/Sections.jsx'; -import { FlexTable, FlexRow, FlexHeader, FlexItem } from '../../common/FlexTable.jsx'; -import styles from './Plans.css'; -const CLOUD_METERED = 'cloud_metered'; -const debug = require('debug')('Plans:'); -const NAUTILUS = 'nautilus'; -import Tooltip from 'rc-tooltip'; -import classnames from 'classnames'; - - -function mkShortPlanIntervalUnit(unit) { - if (unit === 'months'){ - return 'mo'; - } else if (unit === 'years') { - return 'yr'; - } else { - return 'mo'; - } -} - -let mkPricingElement = function(plan) { - var action; - var shortInterval = mkShortPlanIntervalUnit(plan.plan_interval_unit); - var price = parseInt(plan.price_in_cents, 10) / 100; - var pricePerInterval = {price: price, interval: shortInterval}; - - var currentPlanName = this.props.currentPlan.plan || 'free'; - var currentSize = this.getPlanSize(currentPlanName); - debug(currentSize); - if (this.props.JWT) { - if (!!this.props.currentPlan && currentPlanName === plan.plan_code) { - action = 'Current Plan'; - } else if (this.state.confirmPlan === plan.plan_code) { - action = ( -
    - Confirm or  - Cancel -
    - ); - } else if (this.props.updatePlan === plan.plan_code) { - action = ( -
    - Processing -
    - ); - } else if (!!this.props.currentPlan && currentSize > plan.num_private_repos) { - action = (Downgrade Plan); - } else { - action = (Upgrade Plan); - } - } else { - action = ( -
    - Sign up or Log in -
    - ); - } - - return ( - - ); -}; - -function isNautilusEnabled(currentPlan) { - const { add_ons } = currentPlan; - if (!add_ons) { - return false; - } - return _.indexOf(add_ons, NAUTILUS) >= 0; -} - - -var PlanRow = React.createClass({ - displayName: 'PlanRow', - propTypes: { - is_active: PropTypes.bool.isRequired, - num_private_repos: PropTypes.number.isRequired, - name: PropTypes.string.isRequired, - - pricePerInterval: PropTypes.shape({ - price: PropTypes.number.isRequired, - interval: PropTypes.string.isRequired - }), - action: PropTypes.oneOfType([ - PropTypes.string.isRequired, - PropTypes.object.isRequired - ]) - }, - render() { - if (!this.props.is_active) { - return null; - } else { - var ppi = this.props.pricePerInterval; - return ( - - {this.props.name} - ${ppi.price}/{ppi.interval} - {this.props.num_private_repos} - {this.props.num_private_repos} - {this.props.action} - - ); - } - } -}); - -var PlansTable = React.createClass({ - displayName: 'PlansTable', - - contextTypes: { - getStore: React.PropTypes.func.isRequired, - executeAction: React.PropTypes.func.isRequired - }, - - propTypes: { - JWT: PropTypes.string, - username: PropTypes.oneOfType([ - PropTypes.string, PropTypes.bool - ]), - history: PropTypes.object.isRequired, - user: PropTypes.object, - plansList: PropTypes.array.isRequired, - currentPlan: PropTypes.shape({ - subscription_uuid: PropTypes.string, - plan: PropTypes.string, - package: PropTypes.string - }), - stopSubscription: PropTypes.func.isRequired, - billingInfo: PropTypes.object.isRequired, - isNewBilling: PropTypes.bool.isRequired, - updatePlan: PropTypes.string - }, - - getInitialState() { - return { - confirmPlan: '', - hasNautilus: isNautilusEnabled(this.props.currentPlan) - }; - }, - - getPlanSize(plan_code) { - return (_.result(_.find(this.props.plansList, {plan_code: plan_code}), 'num_private_repos')); - }, - - selectConfirmPlan(plan) { - return (e) => { - e.preventDefault(); - this.setState({confirmPlan: plan.plan_code}); - }; - }, - - cancelSelectPlan: function(e) { - e.preventDefault(); - this.setState({confirmPlan: ''}); - }, - - _stopSubscription: function(e) { - e.preventDefault(); - this.setState({confirmPlan: ''}); - this.props.stopSubscription(); - }, - - updateSubscriptionsPlan(plan) { - return (e) => { - e.preventDefault(); - this.setState({confirmPlan: ''}); - if (this.props.isNewBilling) { - // IF USER HAS NO BILLING ACCOUNT OR NO BILLING PAYMENT INFORMATION - // GO TO CREATION PAGE - if (_.has(this.props.user, 'username')) { - this.props.history.pushState(null, '/account/billing-plans/create-subscription/', {plan: plan.plan_code}); - } else if (_.has(this.props.user, 'orgname')) { - this.props.history.pushState(null, `/u/${this.props.user.orgname}/dashboard/billing/create-subscription/`, {plan: plan.plan_code}); - } - } else { - // IF USER HAS BILLING INFORMATION - THEN WE CAN JUST UPGRADE - this.context.executeAction(updateSubscriptionPlanOrPackage, - {JWT: this.props.JWT, - username: this.props.username, - subscription_uuid: this.props.currentPlan.subscription_uuid, - plan_code: plan.plan_code, - package_code: this.props.currentPlan.package - }); - } - }; - }, - - toggleNautilus() { - const { currentPlan, username, JWT } = this.props; - const { plan, subscription_uuid } = currentPlan; - const { hasNautilus } = this.state; - const add_ons = hasNautilus ? [] : [NAUTILUS]; - const data = { - plan_code: plan, - username, - add_ons, - subscription_uuid, - JWT - }; - - this.context.executeAction(updateSubscriptionPlanOrPackage, data); - this.setState({ hasNautilus: !hasNautilus }); - }, - - renderNautilusUpsell() { - const { currentPlan } = this.props; - const isFreePlan = !currentPlan || !currentPlan.plan - || currentPlan.plan === CLOUD_METERED; - let text; - const shield = ( - - - - - - - - - ); - if (isFreePlan) { - text = 'Enable security scanning when you upgrade your plan.'; - const url = 'https://docs.docker.com/docker-cloud/builds/image-scan/'; - const link = ( - - Learn more about Docker Security Scanning - - ); - return ( -
    -
    - {shield} - {text} {link} -
    -
    - ); - } - - var nautilusUpsellClasses = classnames({ - [styles.nautilusUpsell]: true, - [styles.nautilusEnabled]: this.state.hasNautilus - }); - - text = [ - 'Monitor with Docker Security Scanning - available for your private ', - 'repositories for free while in preview.' - ].join(''); - return ( -
    - -
    - ); - }, - - render() { - const {JWT, currentPlan, updatePlan, plansList, isOrg} = this.props; - var action; - if (!JWT) { - action = ( -
    - Sign up or Log in -
    - ); - } else if (!currentPlan.plan || currentPlan.plan === CLOUD_METERED) { - action = 'Current Plan'; - } else if (updatePlan === CLOUD_METERED) { - action = ( -
    Removing Plan
    - ); - } else if (this.state.confirmPlan === 'free') { - action = ( -
    - Confirm or  - Cancel -
    - ); - } else { - action = Downgrade Plan; - } - let allPlans = defaultPlans; - if (!_.isEmpty(plansList)) { - allPlans = _.clone(plansList); - } - const privateRepos = isOrg ? '0' : '1'; - return ( - -
    - - - - Plan - - - Price - - - Private Repositories - - - Parallel Builds - - - - - Free - $0/mo - {privateRepos} - {privateRepos} - {action} - - {allPlans.map(mkPricingElement, this)} -
    - {this.renderNautilusUpsell()} -
    -
    -
    -
    - ); - } -}); - -export default connectToStores(PlansTable, - [PlansStore], - function({ getStore }, props) { - return getStore(PlansStore).getState(); - }); diff --git a/app/scripts/components/account/forms/AccountInfoForm.css b/app/scripts/components/account/forms/AccountInfoForm.css deleted file mode 100644 index 72cf57abed..0000000000 --- a/app/scripts/components/account/forms/AccountInfoForm.css +++ /dev/null @@ -1,21 +0,0 @@ -@import 'dux/css/colors.css'; - -.accountForm { - lost-flex-container: row; -} -.lostFormInputs { - lost-column: 2/3; -} -.accountButtonWrapper { - lost-column: 1/3; - align-self: flex-end; - > * { - lost-column: 1/2; - margin-bottom: 1rem; - } -} - -.error { - color: var(--primary-5); - margin-bottom: 0.3rem; -} diff --git a/app/scripts/components/account/forms/AccountInfoForm.jsx b/app/scripts/components/account/forms/AccountInfoForm.jsx deleted file mode 100644 index 72f34c38cc..0000000000 --- a/app/scripts/components/account/forms/AccountInfoForm.jsx +++ /dev/null @@ -1,133 +0,0 @@ -'use strict'; - -import React from 'react'; -import classnames from 'classnames'; -import connectToStores from 'fluxible-addons-react/connectToStores'; - -import AccountInfoFormStore from '../../../stores/AccountInfoFormStore'; -import SimpleInput from 'common/SimpleInput.jsx'; -import SaveSettings from '../../../actions/saveSettingsData'; -import updateAccountInfoFormField from '../../../actions/updateAccountInfoFormField'; -import Button from '@dux/element-button'; -import { SplitSection } from '../../common/Sections.jsx'; - -import styles from './AccountInfoForm.css'; -import FA from 'common/FontAwesome.jsx'; -import {STATUS as BASE_STATUS} from 'stores/common/Constants.js'; - -var AccountInfoForm = React.createClass({ - contextTypes: { - executeAction: React.PropTypes.func.isRequired - }, - _onChange(fieldKey) { - return (e) => { - this.context.executeAction(updateAccountInfoFormField, { - fieldKey, - fieldValue: e.target.value - }); - }; - }, - onSubmit: function(e) { - e.preventDefault(); - this.context.executeAction(SaveSettings, { - JWT: this.props.JWT, - username: this.props.user.username, - updateData: this.props.values - }); - }, - renderButton: function(STATUS) { - switch (STATUS) { - case BASE_STATUS.SUCCESSFUL: - return ( - - ); - case BASE_STATUS.ERROR: - return ( - - ); - case BASE_STATUS.ATTEMPTING: - return ( - - ); - default: - return ( - - ); - } - }, - render: function() { - const { - full_name, - company, - location, - profile_url, - gravatar_email - } = this.props.fields; - return ( - This information will be visible to all users of Docker Hub.

    }> -
    - -
    -
    - {full_name.error} -
    - - -
    - {company.error} -
    - - -
    - {location.error} -
    - - -
    - {profile_url.error} -
    - - -
    - {gravatar_email.error} -
    - -
    - -
    - { this.renderButton(this.props.STATUS) } -
    - -
    -
    - ); - } -}); - -export default connectToStores(AccountInfoForm, - [ - AccountInfoFormStore - ], - function({ getStore }, props) { - return getStore(AccountInfoFormStore).getState(); - }); diff --git a/app/scripts/components/account/forms/ChangePassForm.css b/app/scripts/components/account/forms/ChangePassForm.css deleted file mode 100644 index 5afebc5a6e..0000000000 --- a/app/scripts/components/account/forms/ChangePassForm.css +++ /dev/null @@ -1,31 +0,0 @@ -@import 'dux/css/colors.css'; -@import 'dux/css/box'; - -.changePassSave { - display: flex; - align-items: flex-end; -} - -.label { - color: #7a8491; -} - -.error { - color: var(--primary-5); - margin-bottom: 0.3rem; -} - -.wrapper { - lost-flex-container: row; -} -.buttons { - lost-column: 1/3; - align-self: flex-end; - > * { - margin-bottom: 1rem; - lost-column: 1/2; - } -} -.lostFormInputs { - lost-column: 2/3; -} diff --git a/app/scripts/components/account/forms/ChangePassForm.jsx b/app/scripts/components/account/forms/ChangePassForm.jsx deleted file mode 100644 index 3e10e2fb7a..0000000000 --- a/app/scripts/components/account/forms/ChangePassForm.jsx +++ /dev/null @@ -1,163 +0,0 @@ -'use strict'; - -import React, { PropTypes } from 'react'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import _ from 'lodash'; -import classnames from 'classnames'; - -import ChangePasswordStore from '../../../stores/ChangePasswordStore'; -import SimpleInput from 'common/SimpleInput.jsx'; -import changePass from '../../../actions/changePassword'; -import updateChangePassStore from '../../../actions/updateChangePassStore'; -import Button from '@dux/element-button'; -import { SplitSection } from '../../common/Sections.jsx'; - -import styles from './ChangePassForm.css'; - -var debug = require('debug')('ChangePassForm'); - -var ChangePassForm = React.createClass({ - contextTypes: { - getStore: PropTypes.func.isRequired, - executeAction: PropTypes.func.isRequired - }, - getDefaultProps: function() { - return { - JWT: '', - username: '' - }; - }, - getInitialState: function() { - return { - confpassErr: '' - }; - }, - onStoreChange: function() { - var store = this.context.getStore(ChangePasswordStore); - this.setState(store.getState()); - }, - oldPassChange: function(e) { - e.preventDefault(); - var oldpass = e.target.value; - var payload = { - oldpass: oldpass, - newpass: this.props.changePasswordStore.newpass, - confpass: this.props.changePasswordStore.confpass - }; - this.context.executeAction(updateChangePassStore, payload); - }, - newPassChange: function(e) { - e.preventDefault(); - var newpass = e.target.value; - var payload = { - oldpass: this.props.changePasswordStore.oldpass, - newpass: newpass, - confpass: this.props.changePasswordStore.confpass - }; - this.context.executeAction(updateChangePassStore, payload); - }, - confirmChange: function(e) { - var confpass = e.target.value; - var payload = { - oldpass: this.props.changePasswordStore.oldpass, - newpass: this.props.changePasswordStore.newpass, - confpass: confpass - }; - this.context.executeAction(updateChangePassStore, payload); - this.setState({ - confpassErr: false - }); - }, - onSubmit: function(e) { - e.preventDefault(); - var store = this.props.changePasswordStore; - if (store.confpass === store.newpass) { - var payload = { - JWT: this.props.JWT, - username: this.props.username, - oldpassword: this.props.changePasswordStore.oldpass, - newpassword: this.props.changePasswordStore.newpass - }; - this.context.executeAction(changePass, payload); - } else { - debug('passwords do not match'); - this.setState({ - confpassErr: true - }); - } - }, - render: function() { - var store = this.props.changePasswordStore; - var oldHasErr = _.has(store.err, 'old_password') || _.has(store.err, 'non_field_errors'); - var oldError; - var newHasErr = _.has(store.err, 'new_password'); - var newError; - if (oldHasErr) { - if (_.has(store.err, 'old_password')) { - oldError = store.err.old_password[0]; - } else { - oldError = store.err.non_field_errors[0]; - } - } - if (newHasErr) { - newError = store.err.new_password[0]; - } - - return ( - Please choose a password which is longer than 6 characters.

    }> -
    -
    -
    - - -
    - { oldError } -
    - - - -
    - { newError } -
    - - - -
    - { this.state.confpassErr ? 'Make sure passwords are identical' : '' } -
    - - -
    -
    - -
    -
    -
    -
    - ); - } -}); - -export default connectToStores(ChangePassForm, - [ChangePasswordStore], - function({ getStore }, props) { - return { - changePasswordStore: getStore(ChangePasswordStore).getState() - }; - }); diff --git a/app/scripts/components/account/forms/EmailForm.css b/app/scripts/components/account/forms/EmailForm.css deleted file mode 100644 index 8a176e8033..0000000000 --- a/app/scripts/components/account/forms/EmailForm.css +++ /dev/null @@ -1,17 +0,0 @@ -@import 'dux/css/colors.css'; -@import 'dux/css/box'; - -.addError { - padding: .5rem .5rem 0 .5rem; - color: var(--primary-5); -} - -.noBottomMargin { - width: 100%; - input { - margin-bottom: 0; - } - > * { - margin-bottom: 0; - } -} diff --git a/app/scripts/components/account/forms/EmailForm.jsx b/app/scripts/components/account/forms/EmailForm.jsx deleted file mode 100644 index 4e98950483..0000000000 --- a/app/scripts/components/account/forms/EmailForm.jsx +++ /dev/null @@ -1,121 +0,0 @@ -'use strict'; - -import React, { PropTypes } from 'react'; -import has from 'lodash/object/has'; -import classnames from 'classnames'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import Button from '@dux/element-button'; -import Card, { Block } from '@dux/element-card'; - -import { SplitSection } from 'common/Sections.jsx'; -import { FlexTable, FlexRow, FlexHeader, FlexItem } from 'common/FlexTable.jsx'; -import SimpleInput from 'common/SimpleInput'; -import EmailElement from './email/EmailElement.jsx'; -import addUserEmail from 'actions/addUserEmail.js'; -import addUserEmailChange from 'actions/addUserEmailChange.js'; -import setNewPrimaryEmail from 'actions/setNewPrimaryEmail'; -import EmailsStore from 'stores/EmailsStore'; - -import styles from './EmailForm.css'; - -var debug = require('debug')('EmailForm'); - -var EmailForm = React.createClass({ - - contextTypes: { - executeAction: React.PropTypes.func.isRequired - }, - propTypes: { - user: PropTypes.object.isRequired, - JWT: PropTypes.string.isRequired, - emails: PropTypes.array.isRequired, - addEmail: PropTypes.string, - addError: PropTypes.string, - emailConfirmations: PropTypes.object - }, - onAddEmailChange: function(e) { - e.preventDefault(); - this.context.executeAction(addUserEmailChange, {email: e.target.value}); - }, - saveNewEmail: function(e) { - e.preventDefault(); - this.context.executeAction(addUserEmail, { - JWT: this.props.JWT, - newEmail: this.props.addEmail, - user: this.props.user - }); - }, - setNewPrimary(id) { - return (e) => { - e.preventDefault(); - var payload = { - JWT: this.props.JWT, - username: this.props.user.username, - emailId: id - }; - this.context.executeAction(setNewPrimaryEmail, payload); - }; - }, - _mkEmailElement({id, user, primary, email, verified}) { - const {emailConfirmations} = this.props; - let emailStatus = ''; - if (has(emailConfirmations, id)) { - emailStatus = emailConfirmations[id]; - } - return (); - }, - render: function() { - const buttonVariant = !this.props.addError ? 'primary' : 'alert'; - let errorMsg; - if (this.props.addError) { - errorMsg = (
    {this.props.addError}
    ); - } - return ( -

    This email address will be used for all notifications and correspondence from Docker.

    -

    If you wish to designate a different email address as primary, first add a new address to your account and then click "make primary".

    )}> - - - -
    - - {errorMsg} - -
    - -
    - -
    -
    -
    - {this.props.emails.map(this._mkEmailElement)} -
    - - ); - } -}); - -export default connectToStores(EmailForm, - [ - EmailsStore - ], function({ getStore }, props) { - return getStore(EmailsStore).getState(); - }); diff --git a/app/scripts/components/account/forms/email/DeleteEmailElement.jsx b/app/scripts/components/account/forms/email/DeleteEmailElement.jsx deleted file mode 100644 index 64c16fdb85..0000000000 --- a/app/scripts/components/account/forms/email/DeleteEmailElement.jsx +++ /dev/null @@ -1,44 +0,0 @@ -'use strict'; - -import React, { PropTypes } from 'react'; -import deleteEmail from 'actions/deleteEmail.js'; -import { FlexItem } from 'common/FlexTable.jsx'; -import styles from './EmailComponents.css'; -import FA from 'common/FontAwesome.jsx'; - -export default React.createClass({ - displayName: 'deleteEmailElement', - propTypes: { - isPrimaryEmail: PropTypes.bool.isRequired, - emailid: PropTypes.number.isRequired, - user: PropTypes.string.isRequired, - JWT: PropTypes.string.isRequired - }, - contextTypes: { - executeAction: PropTypes.func.isRequired - }, - deleteEmail: function(e) { - e.preventDefault(); - var payload = { - JWT: this.props.JWT, - username: this.props.user, - delEmailID: this.props.emailid - }; - this.context.executeAction(deleteEmail, payload); - }, - render() { - if(this.props.isPrimaryEmail) { - return ( - - ); - } else { - return ( - - - - - - ); - } - } -}); diff --git a/app/scripts/components/account/forms/email/EmailComponents.css b/app/scripts/components/account/forms/email/EmailComponents.css deleted file mode 100644 index dc8c95a9c0..0000000000 --- a/app/scripts/components/account/forms/email/EmailComponents.css +++ /dev/null @@ -1,24 +0,0 @@ -@import 'dux/css/colors.css'; - -.emailAddress { - word-wrap: break-word; -} - -.emphasis { - color: var(--secondary-3); - font-weight: 800; -} - -.failed { - color: var(--primary-5); -} - -.remove { - color: var(--primary-5); - transition: color .15s ease; - align-self: center; -} - -.remove:hover { - color: var(--secondary-1); - } diff --git a/app/scripts/components/account/forms/email/EmailElement.jsx b/app/scripts/components/account/forms/email/EmailElement.jsx deleted file mode 100644 index 3fee719c9e..0000000000 --- a/app/scripts/components/account/forms/email/EmailElement.jsx +++ /dev/null @@ -1,56 +0,0 @@ -'use strict'; - -import React, { PropTypes } from 'react'; -import { FlexTable, FlexRow, FlexHeader, FlexItem } from 'common/FlexTable.jsx'; -import styles from './EmailComponents.css'; -import PrimaryEmail from './PrimaryEmail'; -import VerifiedOrResend from './VerifiedOrResend'; -import DeleteEmailElement from './DeleteEmailElement'; - -export default React.createClass({ - displayName: 'EmailElement', - propTypes: { - user: PropTypes.string.isRequired, - isPrimaryEmail: PropTypes.bool.isRequired, - emailid: PropTypes.number.isRequired, - email: PropTypes.string.isRequired, - isVerified: PropTypes.bool.isRequired, - JWT: PropTypes.string.isRequired, - setNewPrimary: PropTypes.func.isRequired, - STATUS: PropTypes.string - }, - render(){ - const { - JWT, - user, - isVerified, - email, - emailid, - isPrimaryEmail, - setNewPrimary, - STATUS - } = this.props; - return ( - - -
    {email}
    -
    - - - -
    - ); - } -}); diff --git a/app/scripts/components/account/forms/email/PrimaryEmail.jsx b/app/scripts/components/account/forms/email/PrimaryEmail.jsx deleted file mode 100644 index 991d7f130a..0000000000 --- a/app/scripts/components/account/forms/email/PrimaryEmail.jsx +++ /dev/null @@ -1,37 +0,0 @@ -'use strict'; - -import React, { PropTypes } from 'react'; -import { FlexItem } from 'common/FlexTable.jsx'; -import styles from './EmailComponents.css'; - -export default React.createClass({ - displayName: 'PrimaryEmail', - propTypes: { - isVerified: PropTypes.bool.isRequired, - isPrimaryEmail: PropTypes.bool.isRequired, - emailID: PropTypes.number.isRequired, - setNewPrimary: PropTypes.func.isRequired - }, - contextTypes: { - executeAction: PropTypes.func.isRequired - }, - render() { - if (!this.props.isVerified) { - return ( - - ); - } else if (this.props.isPrimaryEmail) { - return ( - - primary - - ); - } else { - return ( - - make primary - - ); - } - } -}); diff --git a/app/scripts/components/account/forms/email/VerifiedOrResend.jsx b/app/scripts/components/account/forms/email/VerifiedOrResend.jsx deleted file mode 100644 index 3bfb874368..0000000000 --- a/app/scripts/components/account/forms/email/VerifiedOrResend.jsx +++ /dev/null @@ -1,53 +0,0 @@ -'use strict'; - -import React, { PropTypes } from 'react'; -import resendConfirmationEmail from 'actions/resendConfirmationEmail'; -import { FlexItem } from 'common/FlexTable.jsx'; -import styles from './EmailComponents.css'; -import FA from 'common/FontAwesome.jsx'; -import { EMAILSTATUS } from 'stores/emailsstore/Constants'; - -export default React.createClass({ - displayName: 'VerifiedOrResend', - propTypes: { - isVerified: PropTypes.bool.isRequired, - email: PropTypes.string.isRequired, - emailid: PropTypes.number.isRequired, - STATUS: PropTypes.string - }, - contextTypes: { - executeAction: PropTypes.func.isRequired - }, - _resendConfirmation(e) { - e.preventDefault(); - this.context.executeAction(resendConfirmationEmail, { - JWT: this.props.JWT, - emailID: this.props.emailid - }); - }, - render() { - const { STATUS } = this.props; - if(this.props.isVerified){ - return ( - verified - ); - } else if (STATUS === EMAILSTATUS.ATTEMPTING) { - return (Sending ); - } else if (STATUS === EMAILSTATUS.SUCCESS) { - return (Email Sent!); - } else if (STATUS === EMAILSTATUS.FAILED) { - return ( - -
    Failed
    -
    - ); - } else { - return ( - - Resend Email - - ); - } - } -}); diff --git a/app/scripts/components/account/notificationSettings/EmailNotifForm.css b/app/scripts/components/account/notificationSettings/EmailNotifForm.css deleted file mode 100644 index 4fc8366809..0000000000 --- a/app/scripts/components/account/notificationSettings/EmailNotifForm.css +++ /dev/null @@ -1,25 +0,0 @@ -@import 'dux/css/colors.css'; - -.button { - margin-bottom: -1rem; -} - -.success { - border: 1px solid var(--primary-2); -} - -.formError { - border: 1px solid var(--primary-5); -} - -.checkbox { - padding-top: .5rem; -} - -.notification { - margin-bottom: 1rem; -} -.notification:hover { - cursor: pointer; - cursor: hand; -} diff --git a/app/scripts/components/account/notificationSettings/EmailNotifForm.jsx b/app/scripts/components/account/notificationSettings/EmailNotifForm.jsx deleted file mode 100644 index 0b229c47dd..0000000000 --- a/app/scripts/components/account/notificationSettings/EmailNotifForm.jsx +++ /dev/null @@ -1,158 +0,0 @@ -'use strict'; -import React, { PropTypes } from 'react'; -import _ from 'lodash'; -import classnames from 'classnames'; -import connectToStores from 'fluxible-addons-react/connectToStores'; - -import styles from './EmailNotifForm.css'; - -import EmailNotifStore from '../../../stores/EmailNotifStore.js'; -import deleteEmailNotifs from '../../../actions/deleteEmailNotifs'; -import resetNotifications from '../../../actions/resetNotifications.js'; -import saveEmailNotifs from '../../../actions/saveEmailNotifs'; -import updateNotifCheckbox from '../../../actions/updateNotifCheckbox.js'; -import { Button } from 'dux'; -import { SplitSection } from '../../common/Sections'; -var debug = require('debug')('EmailNotifForm'); - -var EmailNotifForm = React.createClass({ - displayName: 'EmailNotifForm', - contextTypes: { - executeAction: PropTypes.func.isRequired, - getStore: PropTypes.func.isRequired - }, - propTypes: { - user: PropTypes.object.isRequired, - JWT: PropTypes.string.isRequired - }, - onNotifCheckboxClick: function(cboxType, evt) { - this.context.executeAction(updateNotifCheckbox, cboxType); - }, - //TODO: Fix this when we have time to change the backend API. This sucks atm. - _getNotificationPayload: function(type) { - var nType = ''; - switch (type) { - case 'auto': - nType = 'trusted_build_fail'; - break; - case 'star': - nType = 'new_repo_star'; - break; - case 'comment': - nType = 'new_repo_comment'; - break; - } - return { - 'user': this.props.user.username, - 'notification': nType, - 'last_occurrence': '1970-01-01T00:00:00Z' - }; - }, - _getNotificationDeletePayload: function(type) { - switch (type) { - case 'auto': - return this.props.autoBuildNotificationID; - case 'star': - return this.props.starNotificationID; - case 'comment': - return this.props.imgCommentNotificationID; - default: - break; - } - }, - onNotifSubmit: function(e) { - e.preventDefault(); - var store = this.context.getStore(EmailNotifStore); - var changed = store.hasChanged.bind(store); - //TODO: this NEEDS refactoring once we discuss a better way to handle notification settings! eek. - if (changed('star')) { - if (this.props.starNotification) { - var nStar = this._getNotificationPayload('star'); - this.context.executeAction(saveEmailNotifs, {jwt: this.props.JWT, notification: nStar}); - } else { - var nStarDel = this._getNotificationDeletePayload('star'); - if(nStarDel > 0) { - this.context.executeAction(deleteEmailNotifs, {jwt: this.props.JWT, notificationID: nStarDel}); - } - } - } - if (changed('comment')) { - if (this.props.imgCommentNotification) { - var nComment = this._getNotificationPayload('comment'); - this.context.executeAction(saveEmailNotifs, {jwt: this.props.JWT, notification: nComment}); - } else { - var nCommentDel = this._getNotificationDeletePayload('comment'); - if(nCommentDel > 0) { - this.context.executeAction(deleteEmailNotifs, {jwt: this.props.JWT, notificationID: nCommentDel}); - } - } - } - if (changed('auto')) { - if (this.props.autoBuildNotification) { - var nAuto = this._getNotificationPayload('auto'); - this.context.executeAction(saveEmailNotifs, {jwt: this.props.JWT, notification: nAuto}); - } else { - var nAutoDel = this._getNotificationDeletePayload('auto'); - if(nAutoDel > 0) { - this.context.executeAction(deleteEmailNotifs, {jwt: this.props.JWT, notificationID: nAutoDel}); - } - } - } - }, - onNotifCancel: function(e) { - debug('resetting email notifications'); - this.context.executeAction(resetNotifications, ['notifications']); - }, - render: function() { - return ( - The following settings will control how email is sent based on the occurrence of specific events.

    }> -
    -
    -
    - -
    -
    - Notify me when my Repositories get starred -
    -
    -
    -
    - -
    -
    - Notify me when a comment is posted on my Repositories -
    -
    -
    -
    - -
    -
    - Notify me when an automated build fails -
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    - ); - } -}); - -export default connectToStores(EmailNotifForm, - [EmailNotifStore], function({ getStore }, props) { - return getStore(EmailNotifStore).getState(); - }); diff --git a/app/scripts/components/account/orgs/OrganizationAddTeam.jsx b/app/scripts/components/account/orgs/OrganizationAddTeam.jsx deleted file mode 100644 index a703271d72..0000000000 --- a/app/scripts/components/account/orgs/OrganizationAddTeam.jsx +++ /dev/null @@ -1,86 +0,0 @@ -'use strict'; -import React, {Component, PropTypes} from 'react'; -import DUXInput from 'common/DUXInput.jsx'; -import createOrgTeamAction from '../../../actions/createOrgTeam'; -import OrgTeamStore from '../../../stores/OrgTeamStore'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import Button from '@dux/element-button'; -import styles from './TeamProfile.css'; - -import { STATUS as ORG_STATUS } from '../../../stores/orgteamstore/Constants'; -const { string, array, func, object } = PropTypes; - -class OrganizationAddTeam extends Component { - static contextTypes = { - executeAction: func.isRequired - } - - static propTypes = { - JWT: string.isRequired, - onCancel: func, - name: string, - description: string, - members: array, - errorDetails: object, - success: string, - STATUS: string - } - - state = { - teamname: '', - teamdesc: '', - members: [] - } - - _handleCreateTeam = (e) => { - e.preventDefault(); - this.context.executeAction(createOrgTeamAction, - { - jwt: this.props.JWT, - orgName: this.props.params.user, - team: {name: this.state.teamname, description: this.state.teamdesc} }); - } - - _handleReset = (e) => { - e.preventDefault(); - } - - teamNameChange = (e) => { - this.setState({teamname: e.target.value}); - } - - teamDescChange = (e) => { - this.setState({teamdesc: e.target.value}); - } - - render() { - let maybeError; - if (this.props.errorDetails.detail) { - maybeError = {this.props.errorDetails.detail}; - } - return ( -
    -
    - - -
    - - -
    - {maybeError} - -
    - - ); - } -} - -export default connectToStores(OrganizationAddTeam, - [ - OrgTeamStore - ], - function({ getStore }, props) { - return getStore(OrgTeamStore).getState(); - }); diff --git a/app/scripts/components/account/orgs/OrganizationProfile.css b/app/scripts/components/account/orgs/OrganizationProfile.css deleted file mode 100644 index f0e10ae231..0000000000 --- a/app/scripts/components/account/orgs/OrganizationProfile.css +++ /dev/null @@ -1,12 +0,0 @@ -@import "dux/css/colors"; - -.visibility { - color: var(--black); - &, > input { - cursor: pointer; - } -} - -.label { - color: #7a8491; -} diff --git a/app/scripts/components/account/orgs/OrganizationProfile.jsx b/app/scripts/components/account/orgs/OrganizationProfile.jsx deleted file mode 100644 index 6c721405d0..0000000000 --- a/app/scripts/components/account/orgs/OrganizationProfile.jsx +++ /dev/null @@ -1,175 +0,0 @@ -'use strict'; - -import React from 'react'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import _ from 'lodash'; - -import saveOrgProfileAction from '../../../actions/saveOrgProfile'; -import toggleVisibility from '../../../actions/toggleVisibility.js'; -import OrganizationStore from '../../../stores/OrganizationStore'; -import PrivateRepoUsageStore from '../../../stores/PrivateRepoUsageStore.js'; -import SimpleInput from 'common/SimpleInput.jsx'; -import { SplitSection } from '../../common/Sections.jsx'; -import Route404 from '../../common/RouteNotFound404Page.jsx'; -import Button from '@dux/element-button'; -import styles from './OrganizationProfile.css'; - -var OrganizationProfile = React.createClass({ - contextTypes: { - executeAction: React.PropTypes.func.isRequired - }, - propTypes: { - currentOrg: React.PropTypes.shape({ - orgname: React.PropTypes.string, - full_name: React.PropTypes.string, - location: React.PropTypes.string, - company: React.PropTypes.string, - profile_url: React.PropTypes.string - }), - isOwner: React.PropTypes.bool.isRequired, - JWT: React.PropTypes.string, - error: React.PropTypes.string, - success: React.PropTypes.string, - defaultVisibility: React.PropTypes.oneOf(['public', 'private']) - }, - getInitialState: function() { - return { - orgname: this.props.currentOrg.orgname, - fullName: this.props.currentOrg.full_name, - location: this.props.currentOrg.location, - company: this.props.currentOrg.company, - profileUrl: this.props.currentOrg.profile_url, - gravatarEmail: this.props.currentOrg.gravatar_email, - defaultVisibility: this.props.defaultVisibility - }; - }, - onSubmit: function(e) { - e.preventDefault(); - var updatedOrg = { - full_name: this.state.fullName, - location: this.state.location, - company: this.state.company, - profile_url: this.state.profileUrl, - gravatar_email: this.state.gravatarEmail - }; - this.context.executeAction(saveOrgProfileAction, { - jwt: this.props.JWT, - orgname: this.state.orgname, - organization: updatedOrg - }); - this.context.executeAction(toggleVisibility, { - JWT: this.props.JWT, - username: this.state.orgname, - visibility: this.state.defaultVisibility - }); - }, - orgFullNameChange: function(e) { - this.setState({fullName: e.target.value}); - }, - orgCompanyChange: function(e) { - this.setState({company: e.target.value}); - }, - locationChange: function(e) { - this.setState({location: e.target.value}); - }, - profileUrlChange: function(e) { - this.setState({profileUrl: e.target.value}); - }, - gravatarEmailChange: function(e) { - this.setState({gravatarEmail: e.target.value}); - }, - toggleClick: function({ visibility }) { - return (e) => { - this.setState({defaultVisibility: visibility}); - }; - }, - render: function() { - var maybeError = ; - var maybeSuccess = ; - if (this.props.error) { - maybeError = {this.props.error}; - } else if(this.props.success) { - //TODO: this could be an alert box with a close icon that can be closed when the user wants to dismiss - //Or time out after some time (ideally i would like to see this as a notification and that's it) - maybeSuccess =

    {this.props.success}
    ; - } - if (this.props.isOwner) { - return ( -
    -
    - This information is private to users with access to this organization.

    }> -
    -
    -
    -
    - Default Visibility: -
    -
      -
    • - -
    • -
    • - -
    • -
    -
    - - - - - - - - - - - - - - - - - - {maybeError} - {maybeSuccess} - -
    -
    - ); - } else { - return ( - - ); - } - } -}); - -export default connectToStores(OrganizationProfile, - [ - OrganizationStore, - PrivateRepoUsageStore - ], - function({ getStore }, props) { - return _.merge({}, getStore(OrganizationStore).getState(), {defaultVisibility: getStore(PrivateRepoUsageStore).getState().defaultRepoVisibility}); - }); diff --git a/app/scripts/components/account/orgs/TeamProfile.css b/app/scripts/components/account/orgs/TeamProfile.css deleted file mode 100644 index b7cdc43037..0000000000 --- a/app/scripts/components/account/orgs/TeamProfile.css +++ /dev/null @@ -1,7 +0,0 @@ -@import "dux/css/box.css"; - -.addTeamButtonGroup { - button[type="submit"] { - margin-right: var(--default-margin); - } -} diff --git a/app/scripts/components/account/orgs/TeamProfile.jsx b/app/scripts/components/account/orgs/TeamProfile.jsx deleted file mode 100644 index 5fed357741..0000000000 --- a/app/scripts/components/account/orgs/TeamProfile.jsx +++ /dev/null @@ -1,102 +0,0 @@ -'use strict'; - -import React, {PropTypes, Component} from 'react'; -import saveTeamProfileAction from '../../../actions/saveTeamProfile'; -import deleteTeamProfileAction from '../../../actions/removeTeam'; -import DUXInput from 'common/DUXInput.jsx'; -import styles from './TeamProfile.css'; -import Button from '@dux/element-button'; -import _ from 'lodash'; - -const { string, object, bool, func } = PropTypes; - -export default class TeamProfile extends Component { - - static contextTypes = { - executeAction: func.isRequired - } - - static propTypes = { - JWT: string, - history: object.isRequired, - error: string, - success: string, - orgname: string, - clearError: func, - onDeleteTeam: func, - onUpdateTeam: func, - team: object - } - - state = { - teamName: this.props.team.name, - teamDesc: this.props.team.description - } - - onSubmit = (e) => { - e.preventDefault(); - var updatedTeam = { - name: this.state.teamName, - description: this.state.teamDesc - }; - this.context.executeAction(saveTeamProfileAction, { - jwt: this.props.JWT, - orgname: this.props.orgname, - teamname: this.props.team.name, - team: updatedTeam - }); - } - - onDelete = (e) => { - e.preventDefault(); - this.context.executeAction(deleteTeamProfileAction, { - jwt: this.props.JWT, - orgname: this.props.orgname, - teamname: this.props.team.name - }); - } - - teamNameChange = (e) => { - if (this.state.teamName !== 'owners') { - this.setState({teamName: e.target.value}); - } else { - this.setState({teamName: 'owners'}); - } - } - - teamDescChange = (e) => { - this.setState({teamDesc: e.target.value}); - } - - render() { - var maybeError = ; - var maybeSuccess = ; - if (this.props.error) { - maybeError = {this.props.error}; - } else if(this.props.success) { - //TODO: this could be an alert box with a close icon that can be closed when the user wants to dismiss - //Or time out after some time (ideally i would like to see this as a notification and that's it) - maybeSuccess =

    {this.props.success}
    ; - } - var maybeDeleteBtn; - if (this.state.teamName !== 'owners' && this.props.team.name === this.state.teamName) { - maybeDeleteBtn = (); - } - return ( -
    - - -
    - - {maybeDeleteBtn} -
    - {maybeError} - {maybeSuccess} - - ); - } -} diff --git a/app/scripts/components/account/services/GithubLinkScopes.jsx b/app/scripts/components/account/services/GithubLinkScopes.jsx deleted file mode 100644 index b4b56f52b0..0000000000 --- a/app/scripts/components/account/services/GithubLinkScopes.jsx +++ /dev/null @@ -1,86 +0,0 @@ -'use strict'; - -import React from 'react'; -import GithubLinkStore from '../../../stores/GithubLinkStore'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -const debug = require('debug')('COMPONENT:GithubLinkScopes'); -import githubOathAction from '../../../actions/githubOauth'; - -import { SplitSection } from '../../common/Sections'; -import { Button } from 'dux'; - -var GithubLinkScopes = React.createClass({ - displayName: 'GithubLinkScopes', - contextTypes: { - executeAction: React.PropTypes.func.isRequired - }, - _generateGHStateString: function() { - //Generate random string - return Math.random().toString(36).substring(8); - }, - _limitedScope: function(evt) { - evt.preventDefault(); - var ss = this._generateGHStateString(); - window.open( - 'https://github.com/login/oauth/authorize?client_id=' + - this.props.githubClientID + - '&state=' + - ss, '_blank'); - this.context.executeAction(githubOathAction, {stateString: ss}); - }, - _recommendedScope: function(evt) { - evt.preventDefault(); - var ss = this._generateGHStateString(); - window.open( - 'https://github.com/login/oauth/authorize?client_id=' + - this.props.githubClientID + - '&scope=repo' + - '&state=' + - ss, '_blank'); - this.context.executeAction(githubOathAction, {stateString: ss}); - }, - render: function() { - return ( -
    -
    - -
    -
    -
    Public and Private (Recommended)
    -
      -
    • Read and Write access to public and private repositories. - (We only use write access to add service hooks and add deploy keys)
    • -
    • Required if you want to setup an Automated Build from a private GitHub repository.
    • -
    • Required if you want to use a private GitHub organization.
    • -
    • We will automatically configure the service hooks and deploy keys for you.
    • -
    -
    -
    - -
    -
    -
    Limited Access
    -
      -
    • Public read only access.
    • -
    • Only works with public repositories and organizations.
    • -
    • You will need to manually make changes to your repositories in order to use Automated Build.
    • -
    -
    -
    - -
    -
    -
    -
    - ); - } -}); - -export default connectToStores(GithubLinkScopes, - [ - GithubLinkStore - ], - function({ getStore }, props) { - return getStore(GithubLinkStore).getState(); - }); diff --git a/app/scripts/components/common/AlertBox.jsx b/app/scripts/components/common/AlertBox.jsx deleted file mode 100644 index 3a5d5f9f82..0000000000 --- a/app/scripts/components/common/AlertBox.jsx +++ /dev/null @@ -1,34 +0,0 @@ -'use strict'; - -import React, { Component, PropTypes } from 'react'; -const { oneOf, func } = PropTypes; -import { intents } from 'dux/dux/utils/props'; -import classnames from 'classnames'; -import _ from 'lodash'; - -export default class AlertBox extends Component { - static propTypes = { - intent: oneOf(intents), - onClick: func - } - - static defaultProps = { - onClick() {} - } - - render() { - const { intent } = this.props; - - const classes = classnames({ - 'alert-box': true, - [intent]: _.includes(intents, intent) - }); - - return ( -
    - {this.props.children} -
    - ); - } -} diff --git a/app/scripts/components/common/BlankSlate.css b/app/scripts/components/common/BlankSlate.css deleted file mode 100644 index 67bb58242c..0000000000 --- a/app/scripts/components/common/BlankSlate.css +++ /dev/null @@ -1,27 +0,0 @@ -@import 'dux/css/colors.css'; -.blankSlates { - background: #fff; - padding: 2.5rem; - h1 { - color: var(--secondary-7); - font-size: 2rem; - font-weight: 300; - } -} - -.link { - background: transparent; - border-radius: 3px; - border: 1px solid var(--silver); - color: var(--secondary-4); - margin: 0 .3rem .3rem 0; - padding: 1.8rem; - i { - font-size: 2.5em; - margin-bottom: 1rem; - } - &:hover { - background: #f4f9fc; - color: var(--secondary-4); - } -} diff --git a/app/scripts/components/common/BlankSlate.jsx b/app/scripts/components/common/BlankSlate.jsx deleted file mode 100644 index 28bf52acf7..0000000000 --- a/app/scripts/components/common/BlankSlate.jsx +++ /dev/null @@ -1,73 +0,0 @@ -'use strict'; - -import styles from './BlankSlate.css'; -import React, { PropTypes, Component } from 'react'; -import { Link } from 'react-router'; -import FA from './FontAwesome'; -import classnames from 'classnames'; - -const { string, object } = PropTypes; - -/* - * Blankslate - * - * Usage: - * - * - * - * - * - */ - -export class BlankSlates extends Component { - - static propTypes = { - title: string - } - - render() { - return ( -
    -
    -
    -

    {this.props.title}

    -

    {this.props.subtext}

    -
    -
    - {this.props.children} -
    -
    -
    - ); - } -} - -export class BlankSlate extends Component { - static defaultProps = { - query: {} - } - - render() { - const linkClasses = classnames({ - 'button': true, - [styles.link]: true - }); - - const { link, query, icon, title } = this.props; - return ( - -
    {title} - - ); - } -} - -BlankSlate.propTypes = { - link: string.isRequired, - icon: string.isRequired, - title: string, - subtext: string, - query: object -}; diff --git a/app/scripts/components/common/CSEngineBox.css b/app/scripts/components/common/CSEngineBox.css deleted file mode 100644 index 2cd6281e00..0000000000 --- a/app/scripts/components/common/CSEngineBox.css +++ /dev/null @@ -1,24 +0,0 @@ -@import "dux/css/colors"; - -.downloadFlexItem { - background: var(--white); - border: 1px solid var(--iron); - display: flex; - flex-flow: row nowrap; - flex-grow: 4; - flex-basis: 0; - padding: 1rem 1rem; - word-break: break-word; -} - -.curlHelp { - font-size: .875rem; - font-weight: 500; - margin-bottom: 1rem; -} - -.curlWrap { - width: 100%; - padding-left: 1rem; -} - diff --git a/app/scripts/components/common/CSEngineBox.jsx b/app/scripts/components/common/CSEngineBox.jsx deleted file mode 100644 index 8cfb33ea39..0000000000 --- a/app/scripts/components/common/CSEngineBox.jsx +++ /dev/null @@ -1,47 +0,0 @@ -'use strict'; - -import React, { PropTypes, Component } from 'react'; -import CopyCodeBox from 'common/CopyCodeBox'; -import { DEB, RPM } from 'common/data/csEngineInstructions'; -import styles from './CSEngineBox.css'; - -export default class CSEngineBox extends Component { - render() { - return ( -
    -
    -

    Install CS Engine

    -
    -
    - * Copy and run either the RPM or the DEB specific instructions in your terminal. -
    -
    -
    -
    - RPM - -
    -
    -
    -
    - DEB - - - - For more details about this installation,  - - view our documentation - - -
    -
    -
    -
    - ); - } -} diff --git a/app/scripts/components/common/Code.css b/app/scripts/components/common/Code.css deleted file mode 100644 index 0a5a8f177d..0000000000 --- a/app/scripts/components/common/Code.css +++ /dev/null @@ -1,83 +0,0 @@ -.code { - font-family: Consolas, Liberation Mono, Courier, monospace; - /** - * We scope everything rendered in markdown by the above computed - * class. Using :global ensures that we don't have to modify the parser - * to add classes (which would be a turrible idea) in that it styles - * everything *inside of* .code. - */ - :global { - - /** - * Syntax Highlighting - * - * Five-color theme from a single blue hue. - */ - .hljs, pre code[class*="lang-"] { - display: block; - overflow-x: auto; - padding: 0.5em; - background: #eaeef3; - -webkit-text-size-adjust: none; - white-space: pre; - } - - .hljs, - .hljs-list .hljs-built_in { - color: #00193a; - } - - .hljs-keyword, - .hljs-title, - .hljs-important, - .hljs-request, - .hljs-header, - .hljs-doctag { - font-weight: bold; - } - - .hljs-comment, - .hljs-chunk { - color: #738191; - } - - .hljs-string, - .hljs-title, - .hljs-parent, - .hljs-built_in, - .hljs-literal, - .hljs-filename, - .hljs-value, - .hljs-addition, - .hljs-tag, - .hljs-argument, - .hljs-link_label, - .hljs-blockquote, - .hljs-header, - .hljs-name { - color: #0048ab; - } - - .hljs-decorator, - .hljs-prompt, - .hljs-subst, - .hljs-symbol, - .hljs-doctype, - .hljs-regexp, - .hljs-preprocessor, - .hljs-pragma, - .hljs-pi, - .hljs-attribute, - .hljs-attr_selector, - .hljs-xmlDocTag, - .hljs-deletion, - .hljs-shebang, - .hljs-string .hljs-variable, - .hljs-link_url, - .hljs-bullet, - .hljs-sqbracket, - .hljs-phony { - color: #4c81c9; - } - } -} \ No newline at end of file diff --git a/app/scripts/components/common/Code.jsx b/app/scripts/components/common/Code.jsx deleted file mode 100644 index 99ab0adedc..0000000000 --- a/app/scripts/components/common/Code.jsx +++ /dev/null @@ -1,30 +0,0 @@ -'use strict'; - -import React, { PropTypes, Component } from 'react'; -import hljs from 'highlight.js'; -const debug = require('debug')('Code'); -import styles from './Code.css'; - -function renderCode(str) { - const { value } = hljs.highlightAuto(str); - return value; -} - -export default class Code extends Component { - render() { - if(!this.props.children) { - return null; - } - - const html = { - __html: renderCode(this.props.children) - }; - - return ( -
    -
    -
    - ); - } -} diff --git a/app/scripts/components/common/CopyCodeBox.css b/app/scripts/components/common/CopyCodeBox.css deleted file mode 100644 index 377eb21c63..0000000000 --- a/app/scripts/components/common/CopyCodeBox.css +++ /dev/null @@ -1,37 +0,0 @@ -@import "dux/css/box"; -@import "dux/css/colors"; - -.copyBox { - display: flex; - flex-flow: row; - flex-basis: 95%; - margin-right: 1rem; - margin-bottom: 1rem; - overflow-x: auto; - border: 1px solid var(--iron); - border-radius: var(--global-radius); - padding: 0.5rem; -} - -.code { - font-family: monospace; - font-size: .8125em; -} -.contentBox { - composes: code; - white-space: pre; -} - -.dollarBox { - composes: code; - font-weight: 600; - white-space: pre; - user-select: none; -} - -.wrapper { - display: flex; - flex-flow: row nowrap; - align-items: flex-start; - width: 100%; -} \ No newline at end of file diff --git a/app/scripts/components/common/CopyCodeBox.jsx b/app/scripts/components/common/CopyCodeBox.jsx deleted file mode 100644 index f1e7dfa9de..0000000000 --- a/app/scripts/components/common/CopyCodeBox.jsx +++ /dev/null @@ -1,75 +0,0 @@ -'use strict'; - -import React, { PropTypes, Component } from 'react'; -import { findDOMNode } from 'react-dom'; -import styles from './CopyCodeBox.css'; -import Button from '@dux/element-button'; -const debug = require('debug')('CopyCodeBox'); -import repeat from 'lodash/string/repeat'; -const { bool, number, string } = PropTypes; - -export default class CopyCodeBox extends Component { - static propTypes = { - content: string.isRequired, - dollar: bool, - lines: number - } - - static defaultProps = { - dollar: false, - lines: 1 - } - - selectContents = (e) => { - const content = findDOMNode(this.refs.content); - let range; - if ( document.selection ) { - range = document.body.createTextRange(); - range.moveToElementText(content); - range.select(); - } else if ( window.getSelection ) { - range = document.createRange(); - range.selectNodeContents(content); - window.getSelection().removeAllRanges(); - window.getSelection().addRange(range); - } - } - - copyContentsToClipboard = (e) => { - /* Works in Chrome and Firefox 41.x - * TODO: Does not work in Safari - */ - this.selectContents(e); - try { - const success = document.execCommand('copy'); - debug(`Copy worked: ${success}`); - } catch (err) { - debug('Cannot copy.'); - } - } - render() { - const { content, dollar, lines } = this.props; - let dollarDiv; - const button = ( - - ); - if (dollar) { - const inner = repeat('$ \n', lines); - dollarDiv = ( -
    {inner}
    - ); - } - return ( -
    -
    - {dollarDiv} -
    {content}
    -
    - {button} -
    - ); - } -} diff --git a/app/scripts/components/common/DUXInput-b.css b/app/scripts/components/common/DUXInput-b.css deleted file mode 100644 index c5e308bfe3..0000000000 --- a/app/scripts/components/common/DUXInput-b.css +++ /dev/null @@ -1,9 +0,0 @@ -@import "dux/css/colors"; - -:root { - --input-text-color: var(--white); - --label-color: var(--secondary-5); - --highlight-color: var(--primary-color); -} - -@import "./DUXInput-base.css"; \ No newline at end of file diff --git a/app/scripts/components/common/DUXInput-base.css b/app/scripts/components/common/DUXInput-base.css deleted file mode 100644 index d43814cea0..0000000000 --- a/app/scripts/components/common/DUXInput-base.css +++ /dev/null @@ -1,101 +0,0 @@ -/* - * API: - * --label-color - * --input-text-color - * --alert-color - * --highlight-color - */ - -input.duxInput { - padding: 10px 10px 10px 5px; - border: none; - border-bottom: 1px solid gray; - margin: 0; - color: var(--input-text-color); -} -.duxInput:focus { - outline: none; -} - -.group { - position: relative; - margin-bottom: 35px; -} - -.hasError { - border-bottom-color: var(--alert-color); -} - -.hasError .label { - color: var(--alert-color); -} - -.hasError .bar:before, .hasError .bar:after { - background: var(--alert-color); -} - -.label { - color: var(--label-color); - font-weight: normal; - position: absolute; - pointer-events: none; - top: -20px; - transition: 0.2s ease all; -} - -/* BOTTOM BARS ================================= */ -.bar { - position:relative; - display:block; - -} -.bar:before, .bar:after { - content: ''; - height: 2px; - width: 0; - bottom: 0; - position: absolute; - background: var(--highlight-color); - transition: 0.2s ease all; - } -.bar:before { - left: 50%; -} -.bar:after { - right: 50%; -} - -/* HIGHLIGHTER ================================== */ -.highlight { - position: absolute; - height: 60%; - width: 100px; - top: 25%; - left: 0; - pointer-events: none; - transition: 0.2s ease all; - opacity: 0.5; -} - -.duxInput:focus ~ .bar:before { - width: 50%; -} -.duxInput:focus ~ .bar:after { - width: 50%; -} - -.duxInput:focus ~ .highlight { - -webkit-animation: inputHighlighter 0.3s ease; -} - -/* ANIMATIONS ================ */ -@-webkit-keyframes inputHighlighter { - from { - background: var(--highlight-color); - } - to { - width:0; - background:transparent; - } -} - diff --git a/app/scripts/components/common/DUXInput.css b/app/scripts/components/common/DUXInput.css deleted file mode 100644 index fe01e15184..0000000000 --- a/app/scripts/components/common/DUXInput.css +++ /dev/null @@ -1,9 +0,0 @@ -@import "dux/css/colors"; - -:root { - --input-text-color: var(--black); - --label-color: var(--secondary-3); - --highlight-color: var(--primary-color); -} - -@import "./DUXInput-base.css" diff --git a/app/scripts/components/common/DUXInput.jsx b/app/scripts/components/common/DUXInput.jsx deleted file mode 100644 index 722f984db7..0000000000 --- a/app/scripts/components/common/DUXInput.jsx +++ /dev/null @@ -1,130 +0,0 @@ -'use strict'; - -import variantA from './DUXInput.css'; -import variantB from './DUXInput-b.css'; - -import React, { - Component, - PropTypes -} from 'react'; -import { findDOMNode } from 'react-dom'; -const { any, func, string, bool, oneOf } = PropTypes; -import classnames from 'classnames'; -import _ from 'lodash'; -import AlertBox from 'common/AlertBox'; -const debug = require('debug')('DUXInput'); - -export default class DUXInput extends Component { - - static propTypes = { - className: string, - error: string, - hasError: bool.isRequired, - name: string, - onChange: func.isRequired, - success: string, - type: oneOf('hidden text password email search'.split(' ')), - value: string, - variant: string - } - - static defaultProps = { - onChange() { - debug('No onChange function set for Input'); - }, - value: '', - hasError: false, - error: '', - type: 'text', - success: '', - name: '' - } - - focusInput = () => { - findDOMNode(this.refs.input).focus(); - } - - state = { - value: '' - } - - _onChange = (e) => { - // Set local state - const { value } = e.target; - this.setState({ value }); - - // Pass control to onChange controller. Usually a form. - this.props.onChange(e); - } - - componentWillReceiveProps(props) { - /** - * State should be tracked globally in a parent component. As - * such, we need to check the passed in prop against the current - * (local) state value to avoid overwriting the input value. - * - * This prevents a bug which resulted in the cursor being "jumped" - * to the end of an input after every character. - */ - if (props.value !== this.state.value) { - this.setState({ - value: props.value - }); - } - } - - render() { - /** - * Theme variant is accepted through the props. - */ - const { variant, name } = this.props; - const styles = variant !== 'b' ? variantA : variantB; - - /** - * If there is an error, display it - */ - let maybeError = ; - if(this.props.hasError && this.props.error) { - maybeError = {this.props.error}; - } - - /** - * If there is a success message, display it - */ - let maybeSuccess = ; - if(this.props.success) { - /** - * TODO: This shouldn't be a property of the input in the way - * that it currently exists. A field-level success state should - * be very minimal. - * - * OLD_TODO: this could be an alert box with a close icon that can be - * closed when the user wants to dismiss or time out after some - * time (ideally i would like to see this as a notification and - * that's it) - */ - maybeSuccess = {this.props.success}; - } - - const groupClasses = classnames({ - [styles.group]: true, - [styles.hasError]: this.props.hasError - }); - - return ( -
    - - - - {maybeError} - {maybeSuccess} -
    - ); - } -} diff --git a/app/scripts/components/common/FancyInput.css b/app/scripts/components/common/FancyInput.css deleted file mode 100644 index 44264aa907..0000000000 --- a/app/scripts/components/common/FancyInput.css +++ /dev/null @@ -1,76 +0,0 @@ -@import "dux/css/colors.css"; -@import "dux/css/box.css"; - -.inputDiv { - width: 100%; - margin-bottom: 2rem; - > input.default { - padding: 10px 10px 10px 5px; - border: none; - border-bottom: 1px solid #cbcbcb; - margin: 0; - color: #465f77; - &:focus { - outline: none; - } - &:focus::placeholder { - transition: opacity .5s ease; - opacity: .5; - } - } - &.hasError > input { - border-bottom: 1px solid var(--alert-color); - } -} - -.white { - > input.default { - color: var(--white); - border-bottom: 1px solid #465f77; - &::placeholder { - color: #7891b0; - } - } -} - -.hasError { - border-bottom-color: var(--alert-color); - border-radius: var(--global-radius); -} - -.hasError .bar:before, .hasError .bar:after { - background: var(--alert-color); -} - -.bar { - position:relative; - display:block; -} -.bar:before, .bar:after { - content: ''; - height: 2px; - width: 0; - bottom: 0; - position: absolute; - background: var(--primary-color); - transition: 0.2s ease all; - } -.bar:before { - left: 50%; -} -.bar:after { - right: 50%; -} -.default:focus ~ .bar:before { - width: 50%; -} -.default:focus ~ .bar:after { - width: 50%; -} - -.error { - position: absolute; - color: var(--alert-color); - font-weight: 200; - margin: 0 .5rem; -} diff --git a/app/scripts/components/common/FancyInput.jsx b/app/scripts/components/common/FancyInput.jsx deleted file mode 100644 index dd851a808f..0000000000 --- a/app/scripts/components/common/FancyInput.jsx +++ /dev/null @@ -1,99 +0,0 @@ -'use strict'; - -import React, { - Component, - PropTypes -} from 'react'; -import { findDOMNode } from 'react-dom'; -import classnames from 'classnames'; -import styles from './FancyInput.css'; -const { any, func, string, bool, oneOf } = PropTypes; -const debug = require('debug')('SimpleInput'); - -export default class FancyInput extends Component { - static propTypes = { - autoFocus: bool, - hasError: bool, - error: string, - name: string, - onChange: func.isRequired, - placeholder: string, - readOnly: bool, - type: oneOf('hidden text password email search'.split(' ')), - value: any.isRequired, - variant: oneOf(['white']) - } - - static defaultProps = { - hasError: false, - error: '', - onChange() { - debug('No onChange function set for Input'); - }, - value: '', - placeholder: '', - type: 'text', - name: '' - } - - state = { - value: '' - } - - _onChange = (e) => { - // Set local state - const { value } = e.target; - this.setState({ value }); - - // Pass control to onChange controller. Usually a form. - this.props.onChange(e); - } - - componentWillReceiveProps(props) { - /** - * State should be tracked globally in a parent component. As - * such, we need to check the passed in prop against the current - * (local) state value to avoid overwriting the input value. - * - * This prevents a bug which resulted in the cursor being "jumped" - * to the end of an input after every character. - */ - if (props.value !== this.state.value) { - this.setState({ - value: props.value - }); - } - } - - render() { - const { hasError, - error, - name, - placeholder, - readOnly, - type, - value, - variant, - autofocus } = this.props; - const groupClass = classnames({ - [styles.inputDiv]: true, - [styles.white]: variant === 'white', - [styles.hasError]: hasError - }); - - return ( -
    - - -
    {error}
    -
    - ); - } -} diff --git a/app/scripts/components/common/FlexTable.css b/app/scripts/components/common/FlexTable.css deleted file mode 100644 index c05d32354c..0000000000 --- a/app/scripts/components/common/FlexTable.css +++ /dev/null @@ -1,92 +0,0 @@ -@import 'dux/css/colors.css'; -@import 'dux/css/box.css'; - -.defaultBorder { - border: 1px solid var(--secondary-5); -} - -.inACardBorder { - border-bottom: 1px solid var(--secondary-5); -} - -.flexTable { - border-radius: 3px; - color: var(--secondary-2); - display: flex; - flex-flow: column; - justify-content: center; - font-size: 1rem; - font-weight: 400; - line-height: 1.5; - margin-bottom: 1.25rem; -} - -.flexHeader { - background: #f1f6fb; - border-bottom: 1px solid var(--secondary-5); - border-top-left-radius: var(--global-radius); - border-top-right-radius: var(--global-radius); - display: flex; - font-weight: 400; - font-size: 1rem; - padding: 0.3rem; - width: 100%; -} - -.flexRow { - background: var(--white); - border-bottom: 1px solid #e5e5e5; - display: flex; - padding: 0.3rem; - width: 100%; -} - -.flexRow:nth-child(2n+1) { - background: #f9f9f9; -} - -.flexRow:last-child { - border-bottom: 0; - border-bottom-right-radius: var(--global-radius); - border-bottom-left-radius: var(--global-radius); -} - -.selectableFlexRow { - composes: flexRow; - &:hover { - background: var(--silver); - cursor: pointer; - } -} - -.flexItem { - display: flex; - flex-flow: row nowrap; - flex-basis: 0; - padding-left: 1rem; - padding-right: 1rem; - word-break: break-word; -} - -.flexItemPadding { - padding-top: .75rem; - padding-bottom: .75rem; -} - -.flexEnd { - justify-content: flex-end; -} - -@each $num in 1, 2, 3, 4, 5, 6 { - .flexItemGrow$(num) { - flex-grow: $num; - } -} - -.error { - border: 1px solid var(--primary-5); -} - -.success { - border: 1px solid var(--primary-2); -} diff --git a/app/scripts/components/common/FlexTable.jsx b/app/scripts/components/common/FlexTable.jsx deleted file mode 100644 index e7882200db..0000000000 --- a/app/scripts/components/common/FlexTable.jsx +++ /dev/null @@ -1,106 +0,0 @@ -'use strict'; - -import React, { Component, PropTypes } from 'react'; -const { number, bool, func, string } = PropTypes; -import includes from 'lodash/collection/includes'; -import styles from './FlexTable.css'; -import classnames from 'classnames'; - -export class FlexTable extends Component { - static propTypes = { - success: bool, - error: bool, - isWrappedInACard: bool - }; - - static defaultProps = { - isWrappedInACard: false - }; - - render() { - const { error, isWrappedInACard, success } = this.props; - const tableClass = classnames({ - [styles.flexTable]: true, - [styles.defaultBorder]: !isWrappedInACard, - [styles.inACardBorder]: isWrappedInACard, - [styles.success]: success, - [styles.error]: error - }); - - return ( -
    - {this.props.children} -
    - ); - } -} - -export class FlexRow extends Component { - static propTypes = { - onMouseOver: func, - onMouseLeave: func, - onClick: func, - selectable: bool - } - - render() { - const { - onClick, - onMouseOver, - onMouseLeave, - selectable - } = this.props; - return ( -
    - {this.props.children} -
    - ); - } -} - -export class FlexHeader extends Component { - - render() { - return ( -
    - {this.props.children} -
    - ); - } -} - -export class FlexItem extends Component { - - static propTypes = { - grow: number, - end: bool, - noPadding: bool - } - - static defaultProps = { - grow: 1, - noPadding: false - } - - render() { - //Optional itemClass usually used for setting widths - //noPadding removes top and bottom padding - const { grow, end, noPadding } = this.props; - - const itemClass = classnames({ - [styles.flexItem]: true, - [styles.flexEnd]: end, - [styles.flexItemPadding]: !noPadding, - [styles[`flexItemGrow${grow}`]]: includes([1, 2, 3, 4, 5, 6], grow) - }); - - return ( -
    - {this.props.children} -
    - ); - } -} diff --git a/app/scripts/components/common/FontAwesome.jsx b/app/scripts/components/common/FontAwesome.jsx deleted file mode 100644 index 7a09848dd1..0000000000 --- a/app/scripts/components/common/FontAwesome.jsx +++ /dev/null @@ -1,54 +0,0 @@ -'use strict'; - -import React, { Component, PropTypes } from 'react'; -const { oneOf, string, bool } = PropTypes; -import classnames from 'classnames'; -import _ from 'lodash'; -var debug = require('debug')('FontAwesomeIcon'); - -const sizes = ['lg', '2x', '3x', '4x', '5x']; -const animations = ['spin', 'pulse']; -const flips = ['horizontal', 'vertical']; -const rotations = [90, 180, 270]; - -export default class FontAwesome extends Component { - static propTypes = { - icon: string.isRequired, - - animate: oneOf(animations), - fixedWidth: bool, - flip: oneOf(flips), - invert: bool, - rotate: oneOf(rotations), - size: oneOf(sizes), - stack: bool - } - render() { - - const { - animate, - fixedWidth, - flip, - icon, - invert, - rotate, - size, - stack - } = this.props; - - const classes = classnames({ - 'fa': true, - 'fa-fw': fixedWidth, - 'fa-inverse': invert, - [icon]: true, - [`fa-${animate}`]: _.includes(animations, animate), - [`fa-${size}`]: _.includes(sizes, size) && !stack, - [`fa-flip-${flip}`]: _.includes(flips, flip), - [`fa-rotate-${rotate}`]: _.includes(rotations, rotate), - [`fa-stack-${size}`]: _.includes(sizes, size) && stack - }); - - return (); - } -} - diff --git a/app/scripts/components/common/LiLink.jsx b/app/scripts/components/common/LiLink.jsx deleted file mode 100644 index e97162573f..0000000000 --- a/app/scripts/components/common/LiLink.jsx +++ /dev/null @@ -1,17 +0,0 @@ -'use strict'; - -import React from 'react'; -const debug = require('debug')('LiLink: '); -import { Link } from 'react-router'; - -export default class LiLink extends Link { - isActive() { - const { to, query, onlyActiveOnIndex } = this.props; - return this.context.history.isActive(to, query, onlyActiveOnIndex); - } -//In order to show active state on nav links, we need the active class on the li element -//Dependant on Foundation .active class - render() { - return
  • {super.render()}
  • ; - } -} diff --git a/app/scripts/components/common/ListSelector.css b/app/scripts/components/common/ListSelector.css deleted file mode 100644 index fb0cfaa9e4..0000000000 --- a/app/scripts/components/common/ListSelector.css +++ /dev/null @@ -1,32 +0,0 @@ -@import "dux/css/colors.css"; -@import "dux/css/box.css"; - -.header { - font-weight: 400; - padding: 0.5rem; - margin: 0; - background-color: var(--silver); - border: 1px solid var(--secondary-5); - border-top-left-radius: var(--global-radius); - border-top-right-radius: var(--global-radius); -} - -.listSelectorItems { - background: #fff; - list-style: none; - padding: 0; - margin: 0; - border: 1px solid var(--secondary-5); - border-bottom-left-radius: var(--global-radius); - border-bottom-right-radius: var(--global-radius); -} - -.listSelectorItems li { - padding: .5rem; - border-bottom: 1px solid var(--secondary-5); -} - -.listSelectorItems li:hover { - background-color: var(--silver); - cursor: pointer; -} \ No newline at end of file diff --git a/app/scripts/components/common/ListSelector.jsx b/app/scripts/components/common/ListSelector.jsx deleted file mode 100644 index b6fc7f132c..0000000000 --- a/app/scripts/components/common/ListSelector.jsx +++ /dev/null @@ -1,33 +0,0 @@ -'use strict'; - -import React, { PropTypes, Component } from 'react'; -import { StrippedModule } from 'dux'; -import styles from './ListSelector.css'; -import _ from 'lodash'; - -const { string, arrayOf, node } = PropTypes; - -export default class ListSelector extends Component { - - static propTypes = { - header: node, - items: arrayOf(node) - } - - render() { - var header = null; - if (_.isString(this.props.header)) { - header = (
    {this.props.header}
    ); - } else if (_.isObject(this.props.header)) { - header =
    {this.props.header}
    ; - } - - return ( - - {header} -
      - {this.props.items} -
    -
    ); - } -} diff --git a/app/scripts/components/common/Pagination.jsx b/app/scripts/components/common/Pagination.jsx deleted file mode 100644 index 213cc40157..0000000000 --- a/app/scripts/components/common/Pagination.jsx +++ /dev/null @@ -1,119 +0,0 @@ -'use strict'; - -import React, { - PropTypes, - createClass -} from 'react'; -import classnames from 'classnames'; -import _ from 'lodash'; -var debug = require('debug')('Pagination'); - -function noop(e) { - e.preventDefault(); -} - -var Page = createClass({ - displayName: 'Page', - propTypes: { - _onClick: PropTypes.func.isRequired, - pageNumber: PropTypes.number.isRequired, - currentPage: PropTypes.number.isRequired - }, - render() { - var classes = classnames({ - 'current': this.props.currentPage === this.props.pageNumber - }); - - return ( -
  • - {this.props.pageNumber} -
  • - ); - } -}); - -function mkPage(pageNumber) { - return ( - - ); -} - -export default createClass({ - displayName: 'Pagination', - propTypes: { - next: PropTypes.string, - prev: PropTypes.string, - currentPage: PropTypes.number.isRequired, - pageSize: PropTypes.number.isRequired, - onChangePage: PropTypes.func.isRequired - }, - _onClick(pageNumber) { - return (e) => { - //Check if currentPage is to the right of ellipsis and the last from the beginning or the end - //based on whether it is the beginning side or end side, update the page ranges - e.preventDefault(); - this.props.onChangePage(pageNumber); - }; - }, - render() { - var paginationComponent; - // is there a page before this one? - var previousPageExists = !!this.props.prev; - // is there a page after this one? - var nextPageExists = !!this.props.next; - var currentPage = [this.props.currentPage].map(mkPage, this); - var prevClasses = classnames({ - 'arrow': true, - 'unavailable': !previousPageExists - }); - - var nextClasses = classnames({ - 'arrow': true, - 'unavailable': !nextPageExists - }); - - var prevPage = null; - if (previousPageExists) { - prevPage = [( -
  • «
  • - ), ( -
  • {this.props.currentPage - 1}
  • - )]; - } - - var nextPage = null; - if (nextPageExists) { - nextPage = [( -
  • {this.props.currentPage + 1}
  • - ), ( -
  • »
  • - )]; - } - - if (nextPageExists || previousPageExists) { - paginationComponent = ( -
      - {prevPage} - {currentPage} - {nextPage} -
    - ); - } - - return ( -
    - {paginationComponent} -
    - ); - } -}); diff --git a/app/scripts/components/common/PendingDeleteRepositoryItem.css b/app/scripts/components/common/PendingDeleteRepositoryItem.css deleted file mode 100644 index ba66ee2e53..0000000000 --- a/app/scripts/components/common/PendingDeleteRepositoryItem.css +++ /dev/null @@ -1,84 +0,0 @@ -@import "dux/css/colors.css"; -@import "dux/css/box.css"; - -.pendingDeleteItem { - background: var(--white); - border: 1px solid var(--secondary-5); - border-radius: var(--global-radius); - color: var(--secondary-2); - display: flex; - flex-flow: row; - margin: 1rem 0; - font-weight: 500; - cursor: not-allowed; - - &:hover { - border-color: var(--primary-5); - .action { - background-color: var(--primary-1); - color: white; - border-color: var(--primary-1); - } - } -} - -.repoName { - color: var(--primary-1); -} -.avatar { - width: 50px; - height: 50px; - border-radius: var(--global-radius); -} -.officialAvatar { - background: var(--primary-color); -} - -/* sections */ -.section { - display: flex; - border-left: 1px solid var(--secondary-5); - padding: 1rem; -} -.head { - composes: section; - flex-grow: 1; - flex-flow: row; - &:first-child { - border-left: 0; - } -} - -.action { - composes: section; - background-color: var(--secondary-5); - color: var(--secondary-4); - flex-flow: column; - i { - position: relative; - top: 0.5rem; - left: 1.2rem; - } -} -.text { - margin-top: 1.2rem; - margin-left: 0.4rem; - font-size: 0.7rem; -} - -/* "Visibility" Classes */ -.title { - padding-left: 1rem; - padding-right: 1rem; -} -.labels { - color: var(--secondary-4); -} -.pendingDelete { - color: var(--primary-5); -} -/* utility */ -.flexible { - display: flex; - flex: 1; -} diff --git a/app/scripts/components/common/PendingDeleteRepositoryItem.jsx b/app/scripts/components/common/PendingDeleteRepositoryItem.jsx deleted file mode 100644 index 228864aa0d..0000000000 --- a/app/scripts/components/common/PendingDeleteRepositoryItem.jsx +++ /dev/null @@ -1,58 +0,0 @@ -'use strict'; - -import styles from './PendingDeleteRepositoryItem.css'; -import React, { PropTypes, Component } from 'react'; -let { func, string } = PropTypes; -import classnames from 'classnames'; -import FA from 'common/FontAwesome'; -import { mkAvatarForNamespace, isOfficialAvatarURL } from 'utils/avatar'; - -/** - * PendingDeleteRepositoryItem will show only the name and namespace - */ - -export default class PendingDeleteRepositoryItem extends Component { - - static propTypes = { - namespace: string.isRequired, - name: string.isRequired - } - - render() { - - const { - name, - namespace - } = this.props; - - const repoDisplayName = namespace + '/' + name; - const avatar = mkAvatarForNamespace(namespace, name); - const avatarClass = classnames({ - [styles.avatar]: true, - [styles.officialAvatar]: isOfficialAvatarURL(avatar) - }); - - return ( -
  • -
    -
    -
    -
    -
    -
    { repoDisplayName }
    - Deleting... -
    -
    -
    -
    - -
    DETAILS
    -
    -
    -
  • - ); - } -} diff --git a/app/scripts/components/common/RepositoriesList.jsx b/app/scripts/components/common/RepositoriesList.jsx deleted file mode 100644 index a8511c69c4..0000000000 --- a/app/scripts/components/common/RepositoriesList.jsx +++ /dev/null @@ -1,113 +0,0 @@ -'use strict'; - -import React, { PropTypes, createClass } from 'react'; -const { array, bool, element, func, oneOfType } = PropTypes; -import PendingDeleteRepositoryItem from './PendingDeleteRepositoryItem'; -import RepositoryListItem from './RepositoryListItem'; -import { PENDING_DELETE } from 'common/enums/RepoStatus'; -import has from 'lodash/object/has'; - -var debug = require('debug')('RepositoriesList'); - -function mkRepoListItem(repo) { - - const { - is_automated, - is_official, - is_private, - name, - namespace, - pull_count, - repo_name, - star_count, - status - } = repo; - /** - * TODO: after snakecase to camelcase in hub-js-sdk is done remove - * explicit props - */ - if(has(repo, 'is_private')) { - repo.isPrivate = is_private; - } - if(has(repo, 'is_official')) { - repo.isOfficial = is_official; - } - if(has(repo, 'is_offical')) { - // This is a legit typo in the ES results - repo.isOfficial = repo.is_offical; - } - if(has(repo, 'repo_name')) { - repo.repoName = repo_name; - } - - let key = repo_name || (namespace + '/' + name); - - if (status === PENDING_DELETE) { - return ( - - ); - } else { - return ( - - ); - } -} - -var BlankSlate = createClass({ - displayName: 'BlankSlate', - render() { - return ( -
    -
    -
    -

    No Repositories Yet.

    - Create Repository -
    -
    -
    - ); - } -}); - -export default createClass({ - displayName: 'RepositoriesList', - propTypes: { - blankSlate: element, - repos: array.isRequired - }, - getDefaultProps() { - return { - blankSlate: (), - repos: [] - }; - }, - render() { - const { - blankSlate, - repos - } = this.props; - - let content = blankSlate; - - if(repos && repos.length > 0) { - content = ( -
    -
      - {repos.map(mkRepoListItem, this)} -
    -
    - ); - } - - return ( -
    - {content} -
    - ); - } -}); diff --git a/app/scripts/components/common/RepositoryListItem.css b/app/scripts/components/common/RepositoryListItem.css deleted file mode 100644 index c1ee0eeca1..0000000000 --- a/app/scripts/components/common/RepositoryListItem.css +++ /dev/null @@ -1,111 +0,0 @@ -@import "dux/css/colors.css"; -@import "dux/css/box.css"; - -.repositoryListItem { - background: var(--white); - border: 1px solid var(--secondary-5); - border-radius: var(--global-radius); - color: var(--secondary-2); - display: flex; - flex-flow: row; - margin: 1rem 0; - font-weight: 500; - - &:hover { - border-color: var(--primary-1); - .action { - background-color: var(--primary-1); - color: white; - border-color: var(--primary-1); - } - } -} -.repoName { - color: var(--primary-color); -} -.avatar { - width: 60px; - height: 60px; - border-radius: var(--global-radius); - display: flex; -} -.img { - align-self: center; -} -.officialAvatar { - background: var(--primary-color); -} - -/* sections */ -.section { - display: flex; - border-left: 1px solid var(--secondary-5); - padding: 1rem; -} -.head { - composes: section; - flex-grow: 1; - flex-flow: row; - &:first-child { - border-left: 0; - } -} -.stats { - composes: section; - min-width: 100px; - text-align: center; - flex-flow: row; -} -.action { - composes: section; - background-color: var(--secondary-5); - color: var(--secondary-4); - flex-flow: column; - i { - position: relative; - top: 0.5rem; - left: 1.2rem; - } -} -.text { - margin-top: 1.2rem; - margin-left: 0.4rem; - font-size: 0.7rem; -} -/* Stats Boxes */ -.labelValue { - padding-top: 0.25rem; - margin: 0 auto; -} -.value { - margin-bottom: 0.25rem; - color: var(--secondary-4); -} -.subLabel { - color: var(--secondary-4); -} -/* "Visibility" Classes */ -.title { - padding-left: 1rem; - padding-right: 1rem; -} -.labels { - color: var(--secondary-4); -} -/*.official { - color: var(--primary-1); -}*/ -.public { - color: color(var(--primary-1) blackness(50%)); -} -.private { - color: var(--secondary-4); -} -.automated { - color: var(--secondary-4); -} -/* utility */ -.flexible { - display: flex; - flex: 1; -} diff --git a/app/scripts/components/common/RepositoryListItem.jsx b/app/scripts/components/common/RepositoryListItem.jsx deleted file mode 100644 index fbedea3372..0000000000 --- a/app/scripts/components/common/RepositoryListItem.jsx +++ /dev/null @@ -1,326 +0,0 @@ -'use strict'; - -import styles from './RepositoryListItem.css'; -import React, { PropTypes, createClass, Component } from 'react'; -let { string, number } = PropTypes; -import { Link } from 'react-router'; -import classnames from 'classnames'; -import FA from 'common/FontAwesome'; -import numeral from 'numeral'; -import { mkAvatarForNamespace, isOfficialAvatarURL } from 'utils/avatar'; -import isFinite from 'lodash/lang/isFinite'; - -var debug = require('debug')('RepositoryListItem'); - -/* TODO: Should dedupe these render methods */ - -/** - * RepositoryListItem has to handle two versions of a Repository data - * structure. One comes from ElasticSearch, and one comes from Postgres - * - * ElasticSearch: - * - * -- Official - * { - * "repo_name": "ubuntu", - * "is_offical": true, - * "is_automated": false, - * "short_description": "", - * "repo_owner": null, - * "pull_count": 9, - * "star_count": 2 - * } - * - * -- Normal - * { - * "repo_name": "cpuguy83/ubuntu", - * "is_offical": false, - * "is_automated": false, - * "short_description": "ubuntu but more awesome", - * "repo_owner": null, - * "pull_count": 2, - * "star_count": 0 - * } - * - * Postgres: - * - * --Official - * --Normal - * { - * "last_updated": null, - * "pull_count": 9, - * "star_count": 2, - * "can_edit": true, - * "is_automated": false, - * "is_private": false, - * "full_description": null, - * "description": "", - * "status": 1, - * "namespace": "library", - * "name": "ubuntu", - * "user": "jlhawn" - * } - */ - -class Stats extends Component { - static propTypes: { - title: string, - value: number, - inBuckets: bool - } - - formatNumber(n) { - if (n < 1000) { - return numeral(n).format('0a'); - } - return numeral(n).format('0.0a').toUpperCase(); - } - - /** - * Buckets to format the number: - * 10M + - * 5M + - * 1M + - * 500k + - * 100k + - * 50k + - * 10k + - */ - formatBucketedNumber(n) { - if (n < 10000) { - return this.formatNumber(n); - } else if(n < 50000) { - return '10K+'; - } else if(n < 100000) { - return '50K+'; - } else if(n < 500000) { - return '100K+'; - } else if(n < 1000000) { - return '500K+'; - } else if(n < 5000000) { - return '1M+'; - } else if(n < 10000000) { - return '5M+'; - } else { - return '10M+'; - } - } - - render() { - const { value, title, inBuckets } = this.props; - - let statValue; - - if (isFinite(value)) { - if (inBuckets) { - statValue = this.formatBucketedNumber(value); - } else { - statValue = this.formatNumber(value); - } - } else { - return null; - } - - return ( -
    -
    -
    {statValue}
    -
    {title.toUpperCase()}
    -
    -
    - ); - } -} - -var PostgresRepo = createClass({ - displayName: 'PostgresRepo', - propTypes: { - namespace: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - status: PropTypes.number, - description: PropTypes.string, - fullDescription: PropTypes.string, - isPrivate: PropTypes.bool, - isAutomated: PropTypes.bool, - isOfficial: PropTypes.bool, - starCount: PropTypes.number, - pullCount: PropTypes.number - }, - render() { - /** - * Since Official Repos don't show their namespace (library), - * we use this to chop that part off if we need to by redefining - * this variable. - */ - var repoDisplayName = this.props.namespace + '/' + this.props.name; - var linkTo = `/r/${repoDisplayName}/`; - - /** - * visibility can be 'official', 'public' or 'private', with an - * appropriate class to match. - */ - var visibility = null; - var visibilityClasses = {}; - /** - * autobuild is set if this repository is an automated build, otherwise - * we rely on `null` to render nothing. - */ - var autobuild = null; - - if(this.props.isOfficial || this.props.namespace === 'library') { - - visibility = 'official'; - visibilityClasses = classnames({ - [styles.official]: true - }); - repoDisplayName = this.props.name || this.props.repo_name; - linkTo = `/_/${this.props.name}/`; - - } else { - - visibility = 'private'; - if(!this.props.isPrivate) { - visibility = 'public'; - } - visibilityClasses = classnames({ - [styles.public]: !this.props.isPrivate, - [styles.private]: this.props.isPrivate - }); - - if(this.props.isAutomated) { - autobuild = | automated build; - } - } - - const avatar = mkAvatarForNamespace(this.props.namespace, this.props.name); - const avatarClass = classnames({ - [styles.avatar]: true, - [styles.officialAvatar]: isOfficialAvatarURL(avatar) - }); - - return ( -
  • - -
    -
    -
    -
    -
    {repoDisplayName}
    - {visibility} - {autobuild}
    -
    -
    - - -
    - -
    DETAILS
    -
    - -
  • - ); - } -}); - - -var ElasticRepo = createClass({ - displayName: 'ElasticRepo', - propTypes: { - repoName: PropTypes.string.isRequired, - isOfficial: PropTypes.bool.isRequired, - isAutomated: PropTypes.bool.isRequired, - pullCount: PropTypes.number.isRequired, - starCount: PropTypes.number.isRequired - }, - render() { - var repoDisplayName = this.props.repoName; - var linkTo; - - /** - * visibility can be 'official', 'public' or 'private', with an - * appropriate class to match. - */ - var visibility = null; - var visibilityClasses = {}; - /** - * autobuild is set if this repository is an automated build, otherwise - * we rely on `null` to render nothing. - */ - var autobuild = null; - - if(this.props.isOfficial) { - - visibility = 'official'; - visibilityClasses = classnames({ - [styles.official]: true - }); - linkTo = `/_/${this.props.repoName}/`; - - } else { - - let [namespace, splat] = this.props.repoName.split('/'); - linkTo = `/r/${namespace}/${splat}/`; - - if(this.props.isPrivate) { - visibility = 'private'; - } else { - visibility = 'public'; - } - visibilityClasses = classnames({ - [styles.public]: !this.props.isPrivate, - [styles.private]: this.props.isPrivate - }); - - if(this.props.isAutomated) { - autobuild = | automated build; - } - } - - const avatar = mkAvatarForNamespace(this.props.namespace, this.props.repoName); - const avatarClass = classnames({ - [styles.avatar]: true, - [styles.officialAvatar]: isOfficialAvatarURL(avatar) - }); - - return ( -
  • - -
    -
    -
    -
    {repoDisplayName}
    -
    - {visibility} - {autobuild}
    -
    -
    - - -
    - -
    DETAILS
    -
    - -
  • - ); - } -}); - -export default class RepositoryListItem extends Component { - render() { - debug(this.props); - if(this.props.repoName) { - // Render a repo from ElasticSearch - return ( - - ); - } else { - // Render a repo from Postgres - return ( - - ); - } - } -} diff --git a/app/scripts/components/common/RepositoryNameInput.jsx b/app/scripts/components/common/RepositoryNameInput.jsx deleted file mode 100644 index 4a53602878..0000000000 --- a/app/scripts/components/common/RepositoryNameInput.jsx +++ /dev/null @@ -1,42 +0,0 @@ -'use strict'; - -import React, { Component, PropTypes } from 'react'; -import SimpleInput from './SimpleInput'; -const {array, func, string} = PropTypes; - -export default class RepositoryNameInput extends Component { - static propTypes = { - namespaces: array.isRequired, - selectedNamespace: string.isRequired, - repoName: string.isRequired, - onRepoNameChange: func.isRequired, - onNamespaceChange: func.isRequired, - inputClass: string - } - - render() { - - var namespaceOptions = this.props.namespaces.map(function(item, idx) { - return (); - }); - - return ( -
    -
    - -
    -
    - -
    -
    - ); - } -} diff --git a/app/scripts/components/common/RouteNotFound404Page.css b/app/scripts/components/common/RouteNotFound404Page.css deleted file mode 100644 index e1f73119e0..0000000000 --- a/app/scripts/components/common/RouteNotFound404Page.css +++ /dev/null @@ -1,40 +0,0 @@ -@import 'dux/css/colors.css'; -.wrap { - background: var(--docker-dark); - height: 100%; - text-align: center; -} - -.messageModule { - animation: fadein 0.3s; - padding: 1.5rem 0 0 0; - margin: 4rem 0; - width: 800px; -} - -@keyframes fadein { - from { - opacity: 0; - } - to { - opacity: 1; - } -} - -.heading { - color: #71859d; - font-size: 6rem; - font-weight: 400; -} - -.subheading { - color: #cbd5df; - font-weight: 400; -} - -.message { - color: #71859d; - margin: 0 auto; - padding: .5rem; - font-size: 1.1rem; -} diff --git a/app/scripts/components/common/RouteNotFound404Page.jsx b/app/scripts/components/common/RouteNotFound404Page.jsx deleted file mode 100644 index 1eb6acedff..0000000000 --- a/app/scripts/components/common/RouteNotFound404Page.jsx +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; - -import React from 'react'; -import { Module } from 'dux'; -import styles from './RouteNotFound404Page.css'; - -var RouteNotFound404Page = React.createClass({ - displayName: 'RouteNotFound404Page', - render: function() { - return ( -
    -
    -
    -
    -

    404

    -

    Page Not Found

    -

    Sorry, but the page you were trying to view does not exist.

    -
    -
    -
    -
    - ); - } -}); - -module.exports = RouteNotFound404Page; diff --git a/app/scripts/components/common/Row.jsx b/app/scripts/components/common/Row.jsx deleted file mode 100644 index 7d73456638..0000000000 --- a/app/scripts/components/common/Row.jsx +++ /dev/null @@ -1,12 +0,0 @@ -'use strict'; - -import React, { createClass } from 'react'; - -export default createClass({ - displayName: 'Row', - render() { - return ( -
    {this.props.children}
    - ); - } -}); diff --git a/app/scripts/components/common/Sections.css b/app/scripts/components/common/Sections.css deleted file mode 100644 index 7c52eabcbb..0000000000 --- a/app/scripts/components/common/Sections.css +++ /dev/null @@ -1,3 +0,0 @@ -.section { - padding: 1rem 2rem; -} diff --git a/app/scripts/components/common/Sections.jsx b/app/scripts/components/common/Sections.jsx deleted file mode 100644 index 57ed33e7b7..0000000000 --- a/app/scripts/components/common/Sections.jsx +++ /dev/null @@ -1,67 +0,0 @@ -'use strict'; - -import React, { Component, PropTypes } from 'react'; -const { string, node, object, oneOfType, bool } = PropTypes; -import Card, { Block } from '@dux/element-card'; -import styles from './Sections.css'; - -export class SplitSection extends Component { - static propTypes = { - title: string, - subtitle: node, - /** - * module is a props passthrough for precision control over how - * Module displays. An example is setting the `intent` on a module. - */ - module: oneOfType([object, bool]) - }; - static defaultProps = { - module: true - }; - - render() { - var children; - if (this.props.module) { - children = ( - - - {this.props.children} - - - ); - } else { - children = this.props.children; - } - - return ( -
    -
    -
    {this.props.title}
    -
    - {this.props.subtitle} -
    -
    -
    - { children } -
    -
    - ); - } -} - -export class FullSection extends Component { - static propTypes = { - title: string - }; - - render() { - return ( -
    -
    -
    {this.props.title}
    -
    - {this.props.children} -
    - ); - } -} diff --git a/app/scripts/components/common/SimpleInput.css b/app/scripts/components/common/SimpleInput.css deleted file mode 100644 index 562b6227f7..0000000000 --- a/app/scripts/components/common/SimpleInput.css +++ /dev/null @@ -1,23 +0,0 @@ -@import "dux/css/colors.css"; -@import "dux/css/box.css"; - -input.default { - background-color: var(--white); - border-radius: var(--global-radius); -&:focus { - border: 1px solid var(--primary-1); - background-color: var(--white); - } -} - -input.error { - border: 1px solid var(--primary-5); - border-radius: var(--global-radius); -&:focus { - border: 1px solid var(--primary-5); - } -} - -.inputDiv { - width: 100%; -} \ No newline at end of file diff --git a/app/scripts/components/common/SimpleInput.jsx b/app/scripts/components/common/SimpleInput.jsx deleted file mode 100644 index bf8af06b4c..0000000000 --- a/app/scripts/components/common/SimpleInput.jsx +++ /dev/null @@ -1,100 +0,0 @@ -'use strict'; - -import React, { - Component, - PropTypes -} from 'react'; -import { findDOMNode } from 'react-dom'; -import styles from './SimpleInput.css'; -const { any, func, string, bool, oneOf } = PropTypes; -const debug = require('debug')('SimpleInput'); - -/* - * A simpler version of DUXInput without errors / alert boxes - * that is a full field (not a line) - */ -export default class SimpleInput extends Component { - static propTypes = { - autoFocus: bool, - hasError: bool, - name: string, - onChange: func.isRequired, - placeholder: string, - readOnly: bool, - type: oneOf('hidden text password email search'.split(' ')), - value: any.isRequired - } - - static defaultProps = { - hasError: false, - onChange() { - debug('No onChange function set for Input'); - }, - value: '', - placeholder: '', - type: 'text', - name: '' - } - - focusInput = () => { - findDOMNode(this.refs.input).focus(); - } - - state = { - value: '' - } - - _onChange = (e) => { - // Set local state - const { value } = e.target; - this.setState({ value }); - - // Pass control to onChange controller. Usually a form. - this.props.onChange(e); - } - - componentWillReceiveProps(props) { - /** - * State should be tracked globally in a parent component. As - * such, we need to check the passed in prop against the current - * (local) state value to avoid overwriting the input value. - * - * This prevents a bug which resulted in the cursor being "jumped" - * to the end of an input after every character. - */ - if (props.value !== this.state.value) { - this.setState({ - value: props.value - }); - } - } - - componentDidMount() { - const { autoFocus } = this.props; - if (autoFocus) { - this.focusInput(); - } - } - - render() { - const { hasError, - name, - placeholder, - readOnly, - type, - value } = this.props; - const inputClass = hasError ? styles.error : styles.default; - return ( -
    - -
    - ); - } -} diff --git a/app/scripts/components/common/SimpleTextArea.css b/app/scripts/components/common/SimpleTextArea.css deleted file mode 100644 index 280e2ae2d6..0000000000 --- a/app/scripts/components/common/SimpleTextArea.css +++ /dev/null @@ -1,5 +0,0 @@ -@import "dux/css/box.css"; - -.textarea { - border-radius: var(--global-radius); -} \ No newline at end of file diff --git a/app/scripts/components/common/SimpleTextArea.jsx b/app/scripts/components/common/SimpleTextArea.jsx deleted file mode 100644 index d6c76e12c9..0000000000 --- a/app/scripts/components/common/SimpleTextArea.jsx +++ /dev/null @@ -1,89 +0,0 @@ -'use strict'; - -import React, { - Component, - PropTypes -} from 'react'; -import { findDOMNode } from 'react-dom'; -import styles from './SimpleTextArea.css'; -const { any, func, string, number } = PropTypes; -const debug = require('debug')('SimpleTextArea'); - -/* - * A simpler version of DUXInput without errors / alert boxes - * that is a text area - */ -export default class SimpleTextArea extends Component { - static propTypes = { - cols: number, - name: string, - onChange: func.isRequired, - placeholder: string, - rows: number, - value: any.isRequired - } - - static defaultProps = { - onChange() { - debug('No onChange function set for Input'); - }, - cols: 2, - rows: 100, - value: '', - placeholder: '', - name: '' - } - - focusInput = () => { - findDOMNode(this.refs.textarea).focus(); - } - - state = { - value: '' - } - - _onChange = (e) => { - // Set local state - const { value } = e.target; - this.setState({ value }); - - // Pass control to onChange controller. Usually a form. - this.props.onChange(e); - } - - componentWillReceiveProps(props) { - /** - * State should be tracked globally in a parent component. As - * such, we need to check the passed in prop against the current - * (local) state value to avoid overwriting the input value. - * - * This prevents a bug which resulted in the cursor being "jumped" - * to the end of an input after every character. - */ - if (props.value !== this.state.value) { - this.setState({ - value: props.value - }); - } - } - - render() { - const { cols, - rows, - name, - placeholder, - value } = this.props; - return ( -
    - - - ); - } else { - return (); - } - } -} - -module.exports = DeployKeys; diff --git a/app/scripts/components/repo/repoSettings/builds/LinkAutoTrigger.css b/app/scripts/components/repo/repoSettings/builds/LinkAutoTrigger.css deleted file mode 100644 index 4701680485..0000000000 --- a/app/scripts/components/repo/repoSettings/builds/LinkAutoTrigger.css +++ /dev/null @@ -1,53 +0,0 @@ -@import "dux/css/colors.css"; -@import 'dux/css/box.css'; - -.repoName { - padding-right: 0.5rem; -} - -.repoName a { - color: var(--base); - &:hover { - color: var(--primary-1); - } -} - -.removeLink i { - color: var(--base); - cursor: pointer; -} - -.removeLink i:hover { - color: color(var(--base) blackness(20%)); -} - -.success { - -} -.error { - color: var(--primary-5); -} - -.label { - padding: 0.5rem 0; - font-weight: 500; -} - -.tag { - display: flex; - flex-flow: row nowrap; - border-radius: var(--global-radius); - border: 1px solid var(--base); - color: var(--base); - justify-content: flex-start; - align-items: center; - padding: 0.5rem 1rem; - margin: 0 1rem 1rem 0; -} - -.tagsWrapper { - display: flex; - flex-flow: row wrap; - justify-content: flex-start; - align-items: center; -} diff --git a/app/scripts/components/repo/repoSettings/builds/LinkAutoTrigger.jsx b/app/scripts/components/repo/repoSettings/builds/LinkAutoTrigger.jsx deleted file mode 100644 index a0bb73974f..0000000000 --- a/app/scripts/components/repo/repoSettings/builds/LinkAutoTrigger.jsx +++ /dev/null @@ -1,161 +0,0 @@ -'use strict'; - -import React, { - PropTypes, - createClass - } from 'react'; - -import { Link } from 'react-router'; -import addTriggerLink from 'actions/addTriggerLink.js'; -import removeTriggerLink from 'actions/removeTriggerLink.js'; -import updateAutoBuildSettingsStore from 'actions/updateAutoBuildSettingsStore.js'; -import SimpleInput from 'common/SimpleInput.jsx'; -import includes from 'lodash/collection/includes'; -import map from 'lodash/collection/map'; -import { SplitSection } from '../../../common/Sections.jsx'; -import Button from '@dux/element-button'; -import Card, { Block } from '@dux/element-card'; -import FA from '../../../common/FontAwesome.jsx'; -import classnames from 'classnames'; -import styles from './LinkAutoTrigger.css'; - -var debug = require('debug')('BuildOptions'); - -var _mkLinkDisplayRow = function(clickHandler) { - return (repoLink) => { - let username, reponame, link; - if (includes(repoLink.to_repo, '/')) { - [username, reponame] = repoLink.to_repo.split('/'); - link = ( - - {repoLink.to_repo} - - ); - } else { - reponame = repoLink.to_repo; - link = ( - - {reponame} - - ); - } - - return ( -
    -
    - {link} -
    -
    - -
    -
    - ); - }; -}; - -var LinkAutoTrigger = createClass({ - displayName: 'LinkAutoTrigger', - propTypes: { - autoBuildStore: PropTypes.object.isRequired, - autoBuildLinks: PropTypes.array.isRequired, - triggerLinkForm: PropTypes.object.isRequired, - namespace: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - validations: PropTypes.object.isRequired - }, - contextTypes: { - executeAction: React.PropTypes.func.isRequired - }, - _addTriggerLink(e) { - e.preventDefault(); - debug('ADDING TRIGGER LINK'); - let repoName = this.props.triggerLinkForm.repoName; - if (!includes(repoName, '/')) { - repoName = 'library/' + repoName; - } - this.context.executeAction(addTriggerLink, {JWT: this.props.JWT, - namespace: this.props.namespace, - name: this.props.name, - to_repo: repoName}); - }, - _deleteLink: function(repo_id) { - return (e) => { - e.preventDefault(); - this.context.executeAction(removeTriggerLink, {JWT: this.props.JWT, - namespace: this.props.namespace, - name: this.props.name, - repo_id: repo_id}); - }; - }, - _updateFormField(field, key) { - return (e) => { - e.preventDefault(); - this.context.executeAction(updateAutoBuildSettingsStore, {field: field, key: key, value: e.target.value}); - }; - }, - render() { - const { - autoBuildLinks, - triggerLinkForm, - validations - } = this.props; - - let success = validations.links.success ? 'Link successfully added' : null; - let maybeError = null; - const errorClasses = classnames(['large-12 column', styles.error]); - if (validations.links.hasError) { - maybeError = ( -
    - {validations.links.error} -
    - ); - } - let linkedRepos = 'You have not linked any repositories to this Automated Build.'; - if (autoBuildLinks.length) { - linkedRepos = map(autoBuildLinks, _mkLinkDisplayRow(this._deleteLink)); - } - return ( - - -
    -
    -
    -
    - Link your Automated Build to another Docker Hub repository, - and when that repository is updated, it will automatically - trigger a rebuild of this Automated Build. -
    -
    -
    Repository Name
    -
    -
    - -
    -
    - -
    - {maybeError} -
    -
    -
    -
    Linked Repositories
    -
    {linkedRepos}
    -
    -
    -
    -
    -
    -
    - ); - } -}); - -export default LinkAutoTrigger; diff --git a/app/scripts/components/repo/repoSettings/builds/RepoPushTrigger.css b/app/scripts/components/repo/repoSettings/builds/RepoPushTrigger.css deleted file mode 100644 index 9c882cabbf..0000000000 --- a/app/scripts/components/repo/repoSettings/builds/RepoPushTrigger.css +++ /dev/null @@ -1,82 +0,0 @@ -@import 'dux/css/colors.css'; - -.checkText { - margin-left: 1rem; - color: var(--oil); -} - -.button { - float: right; - margin-right: 1.5rem; - margin-top: 1.2rem; -} - -.tableInput { - width: 100%; - input, span, label, div { - width: 100%; - padding: 0; - margin: 0; - } -} - -.table { - border-left-width: 0; - border-top-width: 0; - border-right-width: 0; - margin-bottom: 1 rem; -} - -.faBtn { - cursor: pointer; - user-select: none; - margin-top: 0.8rem; - flex-grow: 1; - display: flex; - justify-content: center; -} - -.addBtn { - composes: faBtn; - color: var(--success-color); -} - -.removeBtn { - composes: faBtn; - color: var(--alert-color); -} - -.noBtn { - flex-grow: 1; -} - -.triggerBtn { - composes: faBtn; - color: var(--primary-color); - margin-left: 0.5rem; -} - -.triggerItem { - display: inherit; -} - -.message { - float: left; - margin-left: .7rem; -} - -.success { - composes: message; - color: var(--success-color); -} - -.error { - composes: message; - color: var(--alert-color); -} - -.clumpedErrors { - composes: error; - font-family: inherit; - font-size: .875rem; -} diff --git a/app/scripts/components/repo/repoSettings/builds/RepoPushTrigger.jsx b/app/scripts/components/repo/repoSettings/builds/RepoPushTrigger.jsx deleted file mode 100644 index 6044876a2b..0000000000 --- a/app/scripts/components/repo/repoSettings/builds/RepoPushTrigger.jsx +++ /dev/null @@ -1,309 +0,0 @@ -'use strict'; - -import React, { - PropTypes, - createClass - } from 'react'; -import SimpleInput from 'common/SimpleInput.jsx'; -import addPushTriggerItem from 'actions/addAutoBuildPushTriggerItem.js'; -import deletePushTriggerItem from 'actions/deleteAutoBuildPushTriggerItem.js'; -import saveRepoPushSettings from 'actions/savePushAutoBuildSettings.js'; -import updatePushTriggerItem from 'actions/updateAutoBuildPushTriggerItem.js'; -import baseClone from 'lodash/internal/baseClone'; -import filter from 'lodash/collection/filter'; -import map from 'lodash/collection/map'; -import isEmpty from 'lodash/lang/isEmpty'; -import isString from 'lodash/lang/isString'; -import remove from 'lodash/array/remove'; -import { Row, Header, Item, FlexTable as Table } from 'common/TagsFlexTable'; -import Button from '@dux/element-button'; -import FA from 'common/FontAwesome.jsx'; -import Card, { Block } from '@dux/element-card'; -import BuildTriggerByTag from './BuildTriggerByTag'; - -import { - SOURCE_NAME_TAG, - SOURCE_NAME_BRANCH, - DOCKER_TAG, - SOURCE_NAME_PLACEHOLDER_BRANCH, - SOURCE_NAME_PLACEHOLDER_TAG, - DOCKER_TAG_PLACEHOLDER_BRANCH, - DOCKER_TAG_PLACEHOLDER_TAG -} from 'common/enums/BuildTagDefault'; - -import styles from './RepoPushTrigger.css'; -var debug = require('debug')('BuildOptions'); - -const _isRegexString = (str) => { - if (isString(str)) { - return (str.charAt(0) === '/' && str.charAt(str.length - 1) === '/'); - } else { - return false; - } -}; - -var RepoPushTrigger = createClass({ - displayName: 'RepoPushTrigger', - propTypes: { - autoBuildStore: PropTypes.object.isRequired, - newTags: PropTypes.array.isRequired, - autoBuildBlankSlate: PropTypes.object.isRequired, - JWT: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - namespace: PropTypes.string.isRequired, - validations: PropTypes.shape({ - buildTags: PropTypes.object.isRequired - }) - }, - contextTypes: { - executeAction: React.PropTypes.func.isRequired - }, - _addPushItem(e) { - e.preventDefault(); - this.context.executeAction(addPushTriggerItem); - }, - _preprocessTags(tags) { - //Remove empty/null values from the tags list - tags = filter(tags, (val) => { - return !isEmpty(val); - }); - //Preprocess tags to send default name/tags in case user doesn't specify - return map(tags, (val) => { - val.source_name = val.source_name || (val.source_type === 'Branch' ? SOURCE_NAME_BRANCH : SOURCE_NAME_TAG); - val.name = val.name || DOCKER_TAG; - return val; - }); - }, - _savePushTrigger(e){ - e.preventDefault(); - const newStripped = remove(this.props.newTags, function(item) { - return !item.toDelete; - }); // remove 'new' build items that have been deleted - let tags = this.props.autoBuildStore.build_tags.concat(newStripped); - - this.context.executeAction(saveRepoPushSettings, { - JWT: this.props.JWT, - name: this.props.name, - namespace: this.props.namespace, - tags: this._preprocessTags(tags) - }); - }, - _updatePushItem(isNew, index, fieldkey) { - // action will handle updates for each field of the build_tag item. - // index comes from mapping through sorted array - return (e) => { - e.preventDefault(); - if (fieldkey === 'delete') { - this.context.executeAction(deletePushTriggerItem, {isNew, index}); - } else { - this.context.executeAction(updatePushTriggerItem, { - isNew, - index, - fieldkey, - value: e.target.value}); - } - }; - }, - _updateSourceType(isNew, index, source_name) { - return (e) => { - e.preventDefault(); - if (e.target.value === 'Tag' && source_name === SOURCE_NAME_BRANCH) { - this.context.executeAction(updatePushTriggerItem, { - isNew, - index, - fieldkey: 'source_name', - value: SOURCE_NAME_TAG}); - } else if (e.target.value === 'Branch' && source_name === SOURCE_NAME_TAG) { - this.context.executeAction(updatePushTriggerItem, { - isNew, - index, - fieldkey: 'source_name', - value: SOURCE_NAME_BRANCH}); - } - this.context.executeAction(updatePushTriggerItem, { - isNew, - index, - fieldkey: 'source_type', - value: e.target.value}); - }; - }, - _renderBuildTagRow(isNew) { - const { - JWT, - name, - namespace - } = this.props; - // isNew needed to differentiate between newly added items and tags from api - let addOrRemove, triggerBuildItem; - return (buildTag, index) => { - if (!buildTag || buildTag.toDelete) { - return (
    ); - } else if (index !== 0 || isNew) { - addOrRemove = ( - - - - ); - } else if (index === 0 && !isNew) { - addOrRemove = ( - - - - ); - } - - // Set defaults - let sourceNamePlaceholder; - let tagNamePlaceholder; - - if (buildTag.source_type === 'Branch') { - sourceNamePlaceholder = SOURCE_NAME_PLACEHOLDER_BRANCH; - tagNamePlaceholder = DOCKER_TAG_PLACEHOLDER_BRANCH; - } else { - sourceNamePlaceholder = SOURCE_NAME_PLACEHOLDER_TAG; - tagNamePlaceholder = DOCKER_TAG_PLACEHOLDER_TAG; - } - - if (buildTag.dockerfile_location === '') { - buildTag.dockerfile_location = '/'; - } - - let displayedTagName; - if (buildTag.name === DOCKER_TAG) { - displayedTagName = ''; - } else { - displayedTagName = buildTag.name; - } - - let displayedSourceName; - let sourceName = SOURCE_NAME_BRANCH; - if ((buildTag.source_name === SOURCE_NAME_BRANCH && buildTag.source_type === 'Branch') || - (buildTag.source_name === SOURCE_NAME_TAG && buildTag.source_type === 'Tag')) { - displayedSourceName = ''; - } else { - displayedSourceName = buildTag.source_name; - } - - let buildTriggerButton = (
    ); - if (!isNew || buildTag.id) { - buildTriggerButton = ( - - ); - } - - return ( - - - - - - - - - - - - - - - {addOrRemove} - {buildTriggerButton} - - - ); - }; - }, - render() { - const { - autoBuildStore, - JWT, - name, - namespace, - newTags, - validations - } = this.props; - - const tags = autoBuildStore.build_tags; - let tagRows; - // _renderBuildTagRow sets index in _updatePushItem - // bool differentiates between new/old build_tags arrays - const newTagRows = map(newTags, this._renderBuildTagRow(true)); - if (isEmpty(tags) && isEmpty(newTags)) { - tagRows = ( - - No push triggers to show - - ); - } else { - // _renderBuildTagRow sets index in _updatePushItem - // bool differentiates between new/old build_tags arrays - tagRows = map(tags, this._renderBuildTagRow(false)); - } - - let saveButtonText = 'Save Changes'; - let saveButtonVariant = 'primary'; - - if (validations.buildTags.success) { - saveButtonText = 'Saved'; - saveButtonVariant = 'success'; - } else if (validations.buildTags.hasError) { - saveButtonText = 'Error Saving'; - saveButtonVariant = 'alert'; - } - - let maybeErrors = ''; - if (validations.buildTags.errors) { - maybeErrors =
    {validations.buildTags.errors.join('\n')}
    ; - } - - return ( -
    -
    -
    - - -
    - Type - Name - Dockerfile Location - Docker Tag Name - -
    - { tagRows } - { newTagRows } -
    -
    -
    - { maybeErrors } -
    -
    - -
    -
    -
    -
    -
    -
    - ); - } -}); - -export default RepoPushTrigger; diff --git a/app/scripts/components/repo/repoSettings/collaborators/Collaborators.css b/app/scripts/components/repo/repoSettings/collaborators/Collaborators.css deleted file mode 100644 index 6165f114ce..0000000000 --- a/app/scripts/components/repo/repoSettings/collaborators/Collaborators.css +++ /dev/null @@ -1,19 +0,0 @@ -@import 'dux/css/colors.css'; -@import 'dux/css/box.css'; - -.table { - width: 100%; -} - -.collaboratorsContent { - padding-top: 1.25rem; -} - -.error { - margin-bottom: var(--default-margin); - color: var(--primary-5); -} - -.button > * { - margin-bottom: 0; -} \ No newline at end of file diff --git a/app/scripts/components/repo/repoSettings/collaborators/Collaborators.jsx b/app/scripts/components/repo/repoSettings/collaborators/Collaborators.jsx deleted file mode 100644 index 85c294425c..0000000000 --- a/app/scripts/components/repo/repoSettings/collaborators/Collaborators.jsx +++ /dev/null @@ -1,181 +0,0 @@ -'use strict'; - -import React, { - Component, - PropTypes - } from 'react'; -const { object, number, string, array, func} = PropTypes; - -import _ from 'lodash'; -import FA from 'common/FontAwesome'; -import Button from '@dux/element-button'; -import addCollaborator from 'actions/addCollaborator'; -import delCollaborator from 'actions/delCollaborator'; -import { STATUS } from 'stores/collaborators/Constants.js'; -import onAddCollaboratorChange from 'actions/onAddCollaboratorChange'; -import Card, { Block } from '@dux/element-card'; -import SimpleInput from 'common/SimpleInput'; -import styles from './Collaborators.css'; -import { - FlexTable, - FlexHeader, - FlexRow, - FlexItem -} from 'common/FlexTable'; -import Pagination from 'common/Pagination.jsx'; - -const debug = require('debug')('RepoCollaborators'); - -class Collaborators extends Component { - - static propTypes = { - count: number.isRequired, - next: string, - previous: string, - results: array.isRequired, - requests: object, - STATUS: string, - newCollaborator: string, - namespace: string.isRequired, - name: string.isRequired, - JWT: string.isRequired, - error: string, - location: object, - history: object - } - - static contextTypes = { - executeAction: func.isRequired - } - - removeUser = (username) => { - const { namespace, name, JWT } = this.props; - return (e) => { - const args = { - JWT, - namespace, - name, - username - }; - this.context.executeAction(delCollaborator, args); - }; - } - - onSubmit = (e) => { - e.preventDefault(); - const { namespace, name, JWT } = this.props; - const args = { - JWT, - namespace, - name, - user: this.props.newCollaborator - }; - this.context.executeAction(addCollaborator, args); - } - - renderTable = () => { - return ( - - - Username - Access - Action - - {this.props.results.map(this.renderTr)} - - ); - } - - renderTr = ({user}) => { - //TODO: Need better way to do validations for deleting collaborators - const status = this.props.requests[user]; - const isLoading = status === 'LOADING'; - const hasError = status === 'ERROR'; - - let icon = ; - if(isLoading) { - icon = ; - } - return ( - - {user} - Collaborator - -
    - -
    -
    -
    - ); - } - - onAddCollaboratorChange = function(e) { - e.preventDefault(); - this.context.executeAction(onAddCollaboratorChange, { collaborator: e.target.value }); - } - - renderAddCollaboratorForm = (collaborator) => { - const { error } = this.props; - const isLoading = this.props.STATUS === STATUS.ATTEMPTING; - const hasError = this.props.STATUS === STATUS.ERROR && error; - let variant = 'primary'; - let errorMsg; - if (hasError) { - variant = 'alert'; - errorMsg =
    {this.props.error}
    ; - } - let button = ; - if(isLoading) { - button = ; - } - - return ( - - -
    - - {errorMsg} - {button} -
    -
    -
    - ); - } - - onChangePage = (pageNumber) => { - debug('onChangePage', pageNumber); - this.props.history.pushState(null, this.props.location.pathname, {page: pageNumber}); - } - - render() { - const { next, prev } = this.props; - const currentPageNumber = parseInt(this.props.location.query.page, 10); - - return ( -
    -
    - {this.renderTable()} - - -
    -
    - {this.renderAddCollaboratorForm(this.props.newCollaborator)} -
    -
    - ); - } -} - -export default Collaborators; diff --git a/app/scripts/components/repo/repoSettings/collaborators/Teams.css b/app/scripts/components/repo/repoSettings/collaborators/Teams.css deleted file mode 100644 index 39ccc894de..0000000000 --- a/app/scripts/components/repo/repoSettings/collaborators/Teams.css +++ /dev/null @@ -1,12 +0,0 @@ -.table { - width: 100%; - margin: 1rem 0; -} - -.teamsWrapper { - padding-top: 1.25rem; -} - -.button > * { - margin-bottom: 0; -} \ No newline at end of file diff --git a/app/scripts/components/repo/repoSettings/collaborators/Teams.jsx b/app/scripts/components/repo/repoSettings/collaborators/Teams.jsx deleted file mode 100644 index ecf0bdf35c..0000000000 --- a/app/scripts/components/repo/repoSettings/collaborators/Teams.jsx +++ /dev/null @@ -1,175 +0,0 @@ -'use strict'; - -import React, { - Component, - PropTypes -} from 'react'; -import { findDOMNode } from 'react-dom'; -const { number, string, array, arrayOf, object, shape, func } = PropTypes; - -import _ from 'lodash'; -import FA from 'common/FontAwesome'; -import Button from '@dux/element-button'; -import Card, { Block } from '@dux/element-card'; -import addTeamCollaborators from 'actions/addTeamCollaborator'; -import delTeamCollaborator from 'actions/delTeamCollaborator'; -import {STATUS} from 'stores/collaborators/Constants.js'; -import styles from './Teams.css'; -import { - FlexTable, - FlexHeader, - FlexRow, - FlexItem -} from 'common/FlexTable'; -import Pagination from 'common/Pagination.jsx'; - -const debug = require('debug')('RepoCollaborators'); - -class Teams extends Component { - - static propTypes = { - count: number.isRequired, - next: string, - previous: string, - results: array.isRequired, - allTeams: arrayOf( - shape({ - group_id: number, - name: string - }) - ), - JWT: string.isRequired, - name: string.isRequired, - namespace: string.isRequired, - requests: object, - location: object, - history: object - } - - static contextTypes = { - executeAction: func.isRequired - } - - removeTeam = (group_id) => { - const { namespace, name, JWT } = this.props; - return (e) => { - debug('Remove Team ', group_id, 'from', `${namespace}/${name}`); - const args = { - JWT, - namespace, - name, - group_id - }; - this.context.executeAction(delTeamCollaborator, args); - }; - } - - onSubmit = (e) => { - e.preventDefault(); - const { JWT, namespace, name, allTeams } = this.props; - const { permissions, team } = this.refs; - const permission = findDOMNode(permissions).value; - const teamName = findDOMNode(team).value; - const { id } = _.find(allTeams, { name: teamName }); - const args = { - JWT, - namespace, - name, - id, - permission - }; - this.context.executeAction(addTeamCollaborators, args); - } - - renderTable = () => { - return ( - - - Team - Access - Action - - {this.props.results.map(this.renderTr)} - - ); - } - - renderTr = ({ group_id, group_name, permission }) => { - //Need better way to do validations for deleting collaborators - const status = this.props.requests[group_id]; - const isLoading = status === STATUS.ATTEMPTING; - const hasError = status === STATUS.ERROR; - - let icon = ; - if(isLoading) { - icon = ; - } - return ( - - {group_name} - {permission} - -
    - -
    -
    -
    - ); - } - - renderAddTeamForm = () => { - const { allTeams } = this.props; - return ( - - -
    - - - -
    -
    -
    - ); - } - - onChangePage = (pageNumber) => { - debug('onChangePage', pageNumber); - this.props.history.pushState(null, this.props.location.pathname, {page: pageNumber}); - } - - render() { - const { next, prev } = this.props; - const currentPageNumber = parseInt(this.props.location.query.page, 10); - - return ( -
    -
    -
    - {this.renderTable()} - - -
    -
    - {this.renderAddTeamForm()} -
    -
    -
    - ); - } -} - -export default Teams; diff --git a/app/scripts/components/repo/repoSettings/settingsMain/DeleteRepositoryForm.css b/app/scripts/components/repo/repoSettings/settingsMain/DeleteRepositoryForm.css deleted file mode 100644 index 2364d2f565..0000000000 --- a/app/scripts/components/repo/repoSettings/settingsMain/DeleteRepositoryForm.css +++ /dev/null @@ -1,19 +0,0 @@ -@import "dux/css/colors.css"; -@import "dux/css/box.css"; - -input.textArea { - background-color: var(--white); - &:focus { - border: 1px solid var(--primary-1); - background-color: var(--white); - } -} - -.text { - margin-bottom: 1rem; -} - -.error { - composes: text; - color: var(--primary-5); -} \ No newline at end of file diff --git a/app/scripts/components/repo/repoSettings/settingsMain/DeleteRepositoryForm.jsx b/app/scripts/components/repo/repoSettings/settingsMain/DeleteRepositoryForm.jsx deleted file mode 100644 index 7c40db1b44..0000000000 --- a/app/scripts/components/repo/repoSettings/settingsMain/DeleteRepositoryForm.jsx +++ /dev/null @@ -1,181 +0,0 @@ -'use strict'; - -import React, { PropTypes, Component } from 'react'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import toggleDeleteRepoNameConfirmBox from 'actions/toggleDeleteRepoNameConfirmBox'; -import updateFormField from 'actions/common/updateFormField'; -import deleteRepositoryAction from 'actions/deleteRepo'; -import DeleteRepoFormStore from 'stores/DeleteRepoFormStore'; -import Card, { Block } from '@dux/element-card'; -import Button from '@dux/element-button'; -import { STATUS as COMMONSTATUS } from 'stores/deleterepostore/Constants'; -import styles from './DeleteRepositoryForm.css'; -const debug = require('debug')('DeleteRepoForm'); -const { string, func, shape, object } = PropTypes; - -class DeleteRepositoryForm extends Component { - static propTypes = { - JWT: string.isRequired, - name: string.isRequired, - params: object.isRequired, - deleteRepoFormStore: shape({ - error: string, - STATUS: string - }) - } - - static contextTypes = { - executeAction: func.isRequired - } - - addEscapeKeyHandler = () => { - document.addEventListener('keydown', this.handleEscapeKey); - } - - removeEscapeKeyHandler = () => { - document.removeEventListener('keydown', this.handleEscapeKey); - } - - handleEscapeKey = (e) => { - e = e || window.event; - const { STATUS } = this.props.deleteRepoFormStore; - if (STATUS !== COMMONSTATUS.DEFAULT && e.keyCode === 27) { - this.toggleConfirmBox(); - } - } - - onChange = (fieldKey) => { - return (e) => { - this.context.executeAction(updateFormField({ - storePrefix: 'DELETE_REPO' - }), { - fieldKey, - fieldValue: e.target.value - }); - }; - } - - onDelete = (e) => { - e.preventDefault(); - const { JWT, name } = this.props; - const { confirmRepoName } = this.props.deleteRepoFormStore.values; - if (confirmRepoName === name) { - const { user, splat } = this.props.params; - this.context.executeAction(deleteRepositoryAction, - { - jwt: JWT, - repoShortName: `${user}/${splat}` - } - ); - } - } - - toggleConfirmBox = (e) => { - this.context.executeAction(toggleDeleteRepoNameConfirmBox); - } - - renderConfirmBox = () => { - const { error, STATUS } = this.props.deleteRepoFormStore; - const { confirmRepoName } = this.props.deleteRepoFormStore.values; - const { name } = this.props; - - const isCorrect = confirmRepoName === name; - let button, maybeError; - if (isCorrect) { - const btnText = STATUS === COMMONSTATUS.ATTEMPTING ? 'Deleting...' - : 'Delete'; - button = ( - - ); - } - if (error) { - maybeError =
    {error}
    ; - } - const confirmTitle = ( -
    - {`Please type the name of your repository to confirm deletion:`} - {name} -
    - ); - const headingActions = [{ - key: 'cancel', - icon: 'fa-remove', - action: this.toggleConfirmBox - }]; - return ( - - - {confirmTitle} -
    - - {maybeError} - {button} -
    -
    -
    - ); - } - - render() { - const { STATUS } = this.props.deleteRepoFormStore; - if (STATUS !== COMMONSTATUS.DEFAULT) { - return this.renderConfirmBox(); - } else { - const button = ( - - ); - const title = `Delete Repository`; - const helpText = ( -
    - Deleting a repository will destroy all images stored within it! - This action is not reversible. -
    - ); - return ( - - -
    -
    -

    {title}

    -
    -
    -
    - {button} -
    -
    -
    -
    -
    -
    - {helpText} -
    -
    -
    -
    -
    - ); - } - } -} - -export default connectToStores(DeleteRepositoryForm, - [ - DeleteRepoFormStore - ], - function({ getStore }, props) { - return { deleteRepoFormStore: getStore(DeleteRepoFormStore).getState() }; - }); diff --git a/app/scripts/components/repo/repoSettings/settingsMain/VisibilityForm.css b/app/scripts/components/repo/repoSettings/settingsMain/VisibilityForm.css deleted file mode 100644 index 5be9fc799d..0000000000 --- a/app/scripts/components/repo/repoSettings/settingsMain/VisibilityForm.css +++ /dev/null @@ -1,19 +0,0 @@ -@import "dux/css/colors.css"; -@import "dux/css/box.css"; - -.text { - margin-bottom: 1rem; -} - -.error { - composes: text; - color: var(--primary-5); -} - -input.textArea { - background-color: var(--white); - &:focus { - border: 1px solid var(--primary-1); - background-color: var(--white); - } -} \ No newline at end of file diff --git a/app/scripts/components/repo/repoSettings/settingsMain/VisibilityForm.jsx b/app/scripts/components/repo/repoSettings/settingsMain/VisibilityForm.jsx deleted file mode 100644 index 5b32b23940..0000000000 --- a/app/scripts/components/repo/repoSettings/settingsMain/VisibilityForm.jsx +++ /dev/null @@ -1,242 +0,0 @@ -'use strict'; - -import React, { PropTypes, Component } from 'react'; -import { Link } from 'react-router'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import toggleVisibilityRepoNameConfirmBox from 'actions/toggleVisibilityRepoNameConfirmBox.js'; -import updateFormField from 'actions/common/updateFormField'; -import updateRepoVisibility from 'actions/updateRepoSettingsVisibilityField'; -import RepoDetailsVisibilityFormStore from 'stores/RepoDetailsVisibilityFormStore.js'; -import { STATUS as COMMONSTATUS } from 'stores/repovisibilitystore/Constants.js'; -import classnames from 'classnames'; -import has from 'lodash/object/has'; -import capitalize from 'lodash/string/capitalize'; -import styles from './VisibilityForm.css'; -import Card, { Block } from '@dux/element-card'; -import Button from '@dux/element-button'; -const { func, bool, shape, number, string, object } = PropTypes; -const debug = require('debug')('VisibilityForm'); - -class VisibilityForm extends Component { - - static propTypes = { - JWT: string.isRequired, - name: string.isRequired, - namespace: string.isRequired, - user: object.isRequired, - visibilityFormStore: shape({ - badRequest: string, - error: string, - success: string, - isPrivate: bool, - numPrivateReposAvailable: number, - privateRepoLimit: number, - STATUS: string, - values: shape({ - confirmRepoName: string - }) - }) - } - - static contextTypes = { - executeAction: func.isRequired - } - - addEscapeKeyHandler = () => { - document.addEventListener('keydown', this.handleEscapeKey); - } - - removeEscapeKeyHandler = () => { - document.removeEventListener('keydown', this.handleEscapeKey); - } - - handleEscapeKey = (e) => { - e = e || window.event; - const { STATUS } = this.props.visibilityFormStore; - if (STATUS !== COMMONSTATUS.DEFAULT && e.keyCode === 27) { - this.toggleConfirmBox(); - } - } - - updateVisibility = (visibility, isDisabled) => { - return (e) => { - e.preventDefault(); - const { JWT, namespace, name } = this.props; - if (!isDisabled) { - this.context.executeAction(updateRepoVisibility, - { - jwt: JWT, - repoShortName: namespace + '/' + name, - isPrivate: (visibility === 'private') - }); - } - }; - } - - toggleConfirmBox = (e) => { - this.context.executeAction(toggleVisibilityRepoNameConfirmBox); - } - - onChange = (fieldKey) => { - return (e) => { - this.context.executeAction(updateFormField({ - storePrefix: 'REPO_DETAILS_VISIBILITY' - }), { - fieldKey, - fieldValue: e.target.value - }); - }; - } - - isOrg = () => { - const { user, namespace } = this.props; - // username is the logged in user. namespace is the current org / user - // if namespace != username, then it is an org - if (has(user, 'username')) { - return user.username !== namespace; - } else { - //if there is no user.username, there is an user.orgname - return true; - } - } - - getBillingLink = () => { - const { namespace } = this.props; - const linkToBilling = this.isOrg() ? `/u/${namespace}/dashboard/billing/` : '/account/billing-plans/'; - return ( - - Get more private repositories. - - ); - } - - renderConfirmBox = () => { - const { badRequest, - isPrivate, - error, - STATUS } = this.props.visibilityFormStore; - const { confirmRepoName } = this.props.visibilityFormStore.values; - const { name } = this.props; - const isCorrect = confirmRepoName === name; - const newVisibility = isPrivate ? 'public' : 'private'; - let button, maybeError; - if (isCorrect) { - const btnText = STATUS === COMMONSTATUS.ATTEMPTING ? 'Submitting...' - : 'Confirm'; - button = ( - - ); - } - if (error || badRequest) { - maybeError =
    {error || badRequest}
    ; - } - const confirmTitle = ( -
    - {`Please type the name of your repository to make it ${newVisibility}:`} - {name} -
    - ); - const headingActions = [{ - key: 'cancel', - icon: 'fa-remove', - action: this.toggleConfirmBox - }]; - return ( - - - {confirmTitle} -
    - - {maybeError} - {button} -
    -
    -
    - ); - } - - render() { - const { badRequest, - error, - isPrivate, - numPrivateReposAvailable, - privateRepoLimit, - STATUS } = this.props.visibilityFormStore; - - if (STATUS !== COMMONSTATUS.DEFAULT) { - return this.renderConfirmBox(); - } else { - const newVisibility = isPrivate ? 'public' : 'private'; - let privateDisabled = numPrivateReposAvailable === 0; - let helpText; - const button = ( - - ); - const title = `Make this Repository ${capitalize(newVisibility)}`; - - if (isPrivate) { - helpText = `Public repositories are available to anyone and will ` + - `appear in public search results. `; - } else { - let numLeftText; - if (numPrivateReposAvailable !== null && privateRepoLimit !== null) { - numLeftText = `You are using ` + - `${privateRepoLimit - numPrivateReposAvailable} of ` + - `${privateRepoLimit} private repositories. `; - } - if (privateDisabled) { - helpText = (
    {numLeftText}{this.getBillingLink()}
    ); - } else { - const privateText = `Private repositories are only available to you or members of your organization. `; - helpText =
    {privateText}
    {numLeftText}
    ; - } - } - return ( - - -
    -
    -

    {title}

    -
    -
    -
    - {button} -
    -
    -
    -
    -
    -
    - {helpText} -
    -
    -
    -
    -
    - ); - } - } -} - -export default connectToStores( - VisibilityForm, - [ RepoDetailsVisibilityFormStore ], - function({ getStore }, props) { - return {visibilityFormStore: getStore(RepoDetailsVisibilityFormStore).getState()}; - } -); diff --git a/app/scripts/components/repo/repoSettings/webhooks/AddWebhookForm.css b/app/scripts/components/repo/repoSettings/webhooks/AddWebhookForm.css deleted file mode 100644 index 4915ab4b0f..0000000000 --- a/app/scripts/components/repo/repoSettings/webhooks/AddWebhookForm.css +++ /dev/null @@ -1,148 +0,0 @@ -.form { - margin: 12px 0; - padding: 22px; - background: #FBFBFC; - border: 1px solid #C4CDDA; - border-radius: 2px; -} - -.formError { - margin-right: 10px; - color: #DC7D7D; - font-size: 14px; - line-height: 20px; - text-align: right; -} - -.formRow { - display: flex; - justify-content: space-between;; - align-items: center; - flex-wrap: wrap; - margin: 0 -10px; - - &.formRowActions { - justify-content: flex-end; - margin: 0 -5px 0; - - .button { - margin-top: 12px; - } - } -} - -.label { - margin: 0 0 10px; - font-size: 14px; - color: #C4CDDA; - line-height: 20px; - transition: all 100ms ease-in; -} - -input[type=text].input, -input[type=url].input { - display: block; - margin: 0; - padding: 0; - width: 100%; - height: 20px; - border: none; - border-bottom: 1px solid #C4CDDA; - font-size: 14px; - color: #3F5167; - line-height: 20px; - transition: all 100ms ease-in; - - &:focus { - border-bottom-color: #22B8EB; - /*Use box-shadow to thicken bottom border without jumping*/ - box-shadow: 0 1px #22B8EB; - } - - &:not(.input_empty):invalid { - border-bottom-color: #EB2222; - box-shadow: 0 1px #EB2222; - - & + .inputError { - opacity: 1; - } - } -} - -.inputError { - color: #DC7D7D; - margin-top: 1px; - font-size: 10px; - line-height: 14px; - opacity: 0; - transition: opacity 100ms ease-in; -} - -.inputGroup { - flex-grow: 1; - margin: 10px; - width: 200px; - - .label { - position: relative; - margin-top: -20px; - margin-bottom: 0; - transform-origin: bottom left; - } - - .input { - &::placeholder { - opacity: 0; - transition: opacity 100ms ease-in; - } - - &:focus::placeholder { - opacity: 1; - } - - &:not(.input_empty):invalid + .label + .inputError { - opacity: 1; - } - - &:focus + .label, - &:not(.input_empty) + .label { - color: #B2BBC8; - transform: translateY(-20px) scale(0.7); - } - } -} - -.button { - padding: 8px 20px; - margin: 0 5px; - font-size: 14px; - font-weight: 500; - line-height: 20px; - border-radius: 2px; - transition: all 100ms ease-in; - - &:disabled { - opacity: 0.5; - } - - &.buttonPrimary { - background: #22B8EB; - color: #FFFFFF; - border: none; - - &:not(:disabled):hover { - background: #13A3D4; - } - } - - &.buttonSecondary { - background: #FCFDFF; - color: #22B8EB; - border: 1px solid #22B8EB; - - &:not(:disabled):hover { - border-color: #13A3D4; - color: #13A3D4; - } - } -} diff --git a/app/scripts/components/repo/repoSettings/webhooks/AddWebhookForm.jsx b/app/scripts/components/repo/repoSettings/webhooks/AddWebhookForm.jsx deleted file mode 100644 index 3be0d5cb91..0000000000 --- a/app/scripts/components/repo/repoSettings/webhooks/AddWebhookForm.jsx +++ /dev/null @@ -1,252 +0,0 @@ -'use strict'; - -import React, { - PropTypes, - Component -} from 'react'; - -import connectToStores from 'fluxible-addons-react/connectToStores'; -import AddWebhookFormStore from 'stores/AddWebhookFormStore'; -import JWTStore from 'stores/JWTStore'; - -import { - DEFAULT, ATTEMPTING, ERROR -} from 'stores/addwebhookformstore/Constants'; - -import addPipeline from 'actions/addPipeline'; -import resetForm from 'actions/resetWebhookForm'; - -const debug = require('debug')('AddWebhookForm.jsx'); -import styles from './AddWebhookForm.css'; - -class AddWebhookForm extends Component { - static propTypes = { - namespace: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - STATUS: PropTypes.oneOf([DEFAULT, ATTEMPTING, ERROR]), - cancel: PropTypes.func.isRequired, - serverErrors: PropTypes.object - } - - static defaultProps = { - STATUS: DEFAULT, - serverErrors: {} - } - - static contextTypes = { - getStore: PropTypes.func.isRequired, - executeAction: PropTypes.func.isRequired - } - - state = { - form: 'invalid', - pipelineName: 'empty', - hookUrl: 'empty' - } - - componentDidMount() { - this.refs.pipelineName.focus(); - } - - componentWillUnmount() { - this.context.executeAction(resetForm); - } - - componentWillReceiveProps(nextProps) { - if (nextProps.STATUS === ERROR && this.state.form !== 'invalid') { - this.setState({form: 'valid'}); - } - } - - validateForm() { - const valid = this.refs.form.checkValidity(); - this.setState({ - form: valid ? 'valid' : 'invalid' - }); - - return valid; - } - - validateInput(name) { - const input = this.refs[name]; - const value = input.value; - const valid = input.checkValidity(); - - let inputState; - - if(value === '') { - inputState = 'empty'; - } else { - inputState = valid ? 'valid' : 'invalid'; - } - - this.setState({[name]: inputState}); - return valid; - } - - possiblyRenderServerError() { - if (this.props.STATUS !== ERROR) { - return undefined; - } - - const messages = []; - - try { - const response = this.props.serverErrors.response.body; - Object.keys(response).forEach((key) => { - if (key === 'webhooks') { - messages.push(response[key][0].hookUrl[0]); - } else { - messages.push(response[key]); - } - }); - } catch (e) { - messages.push('Something went wrong! Please try again.'); - } - - return ( -
    - {messages.join(
    )} -
    - ); - } - - onInputUpdated(name) { - this.validateInput(name); - this.validateForm(); - } - - onClickCancel(event) { - event.preventDefault(); - this.props.cancel(); - } - - onFormKeyUp(event) { - // Look for press of escape key - if (event.which === 27) { - this.onClickCancel(event); - } - } - - onSubmit(event) { - event.preventDefault(); - - if (this.state.form !== 'valid') { - return; - } - - this.setState({ - form: 'submitting', - serverErrors: null - }); - - const { jwt, namespace, name } = this.props; - - const webhooks = [{hookUrl: this.refs.hookUrl.value}]; - - this.context.executeAction(addPipeline, { - jwt, - namespace, - name, - pipelineName: this.refs.pipelineName.value, - webhooks - }); - } - - render() { - const formClasses = [styles.form]; - const pipelineNameClasses = [styles.input]; - const hookUrlClasses = [styles.input]; - - formClasses.push(styles[`form_${this.state.form}`]); - pipelineNameClasses.push(styles[`input_${this.state.pipelineName}`]); - hookUrlClasses.push(styles[`input_${this.state.hookUrl}`]); - - return ( -
    -
    -
    - - -
    - Must be at least 3 chars -
    -
    -
    - - -
    - Valid URL required -
    -
    -
    -
    - {this.possiblyRenderServerError()} - - -
    -
    - ); - } -} -export default connectToStores( - AddWebhookForm, - [ - AddWebhookFormStore, - JWTStore - ], - ({ getStore }, props) => { - const webhookData = getStore(AddWebhookFormStore).getState(); - const { jwt } = getStore(JWTStore).getState(); - return { - ...webhookData, - jwt - }; - } -); diff --git a/app/scripts/components/repo/repoSettings/webhooks/Pipeline/History.css b/app/scripts/components/repo/repoSettings/webhooks/Pipeline/History.css deleted file mode 100644 index 4f1e25b5ce..0000000000 --- a/app/scripts/components/repo/repoSettings/webhooks/Pipeline/History.css +++ /dev/null @@ -1,63 +0,0 @@ -.history { - margin-top: 32px; - padding-top: 32px; - border-top: 1px solid #C4CDDA; - font-size: 12px; -} - -.title { - font-size: 12px; - color: #7A8491; - line-height: 16px; - margin-bottom: 12px; - text-transform: uppercase; -} - -.loading, -.empty { - margin: 0; - text-align: center; - font-style: italic; - color: #7A8491; -} - -.attempts { - width: 100%; - margin: 0; - font-size: 14px; - line-height: 20px; - color: #B2BBC8; - border: none; - background: none; - - & > thead { - background: none; - border: none; - - & > tr > th { - font-weight: 500; - font-size: 13px; - color: #C4CDDA; - } - } - - & > tbody > tr { - background: none; - border: none; - - & > td { - background: none; - color: #B2BBC8; - - &.uuid { - font-family: monospace; - color: #22B8EB; - overflow-wrap: break-word; - word-wrap: break-word; - -ms-word-break: break-all; - word-break: break-all; - word-break: break-word; - } - } - } -} diff --git a/app/scripts/components/repo/repoSettings/webhooks/Pipeline/History.jsx b/app/scripts/components/repo/repoSettings/webhooks/Pipeline/History.jsx deleted file mode 100644 index 77fdb44342..0000000000 --- a/app/scripts/components/repo/repoSettings/webhooks/Pipeline/History.jsx +++ /dev/null @@ -1,101 +0,0 @@ -'use strict'; -import React, { Component, PropTypes } from 'react'; -import moment from 'moment'; -import getPipelineHistory from 'actions/getPipelineHistory'; - -import Status from './Status.jsx'; -import styles from './History.css'; - -export default class PipelineHistory extends Component { - static propTypes = { - namespace: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - slug: PropTypes.string.isRequired, - attempts: PropTypes.arrayOf(PropTypes.shape({ - created: PropTypes.string, - status: PropTypes.string, - uuid: PropTypes.string - })) - } - - static contextTypes = { - executeAction: PropTypes.func.isRequired - } - - state = { - loading: true - } - - componentDidMount() { - const { JWT: jwt, namespace, name, slug } = this.props; - this.context.executeAction(getPipelineHistory, { - jwt, namespace, name, slug - }); - } - - componentWillReceiveProps(nextProps) { - if (nextProps.attempts) { - this.setState({loading: false}); - } - } - - renderPipelineAttempt({ created, status, uuid }) { - return ( - - - {uuid} - - - - - - {moment(created).format('MM/DD/YY HH:mm')} - - - ); - } - - renderEmptyMessage() { - return ( -

    No history for this webhook

    - ); - } - - renderLoadingMessage() { - return ( -

    Loading history...

    - ); - } - - renderLoadingOrHistoryOrEmptyMessage() { - if (this.state.loading) { - return this.renderLoadingMessage(); - } else if (this.props.attempts && this.props.attempts.length) { - return ( - - - - - - - - - - {this.props.attempts.map(this.renderPipelineAttempt, this)} - -
    IDStatusDate & Time
    - ); - } else { - return this.renderEmptyMessage(); - } - } - - render() { - return ( -
    -
    History
    - {this.renderLoadingOrHistoryOrEmptyMessage()} -
    - ); - } -} diff --git a/app/scripts/components/repo/repoSettings/webhooks/Pipeline/Options.css b/app/scripts/components/repo/repoSettings/webhooks/Pipeline/Options.css deleted file mode 100644 index 36cf9c3da7..0000000000 --- a/app/scripts/components/repo/repoSettings/webhooks/Pipeline/Options.css +++ /dev/null @@ -1,146 +0,0 @@ -.options { - font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; -} - -.options_showMenu { - box-sizing: content-box; - position: relative; - cursor: pointer; - padding: 2px 4px; - width: 4px; - height: 16px; - - /* Use pseudo element + box shadows to create 3 dots */ - &::before { - content: ''; - display: block; - width: 4px; - height: 4px; - border-radius: 2px; - background: #C4CDDA; - box-shadow: 0 6px 0 0 #C4CDDA, 0 12px 0 0 #C4CDDA; - transition: all 100ms ease-in; - } - - &:hover { - &::before { - background: #7A8491; - box-shadow: 0 6px 0 0 #7A8491, 0 12px 0 0 #7A8491; - } - - /* Use pseudo element to cover space behind carrot for better hover ux */ - &::after { - content: ''; - display: block; - box-sizing: content-box; - position: absolute; - right: -8px; - bottom: -8px; - padding: 0 8px 0 20px; - width: 100%; - height: 14px; - } - - .menu { - opacity: 1; - pointer-events: all; - } - } -} - -.menu { - position: absolute; - top: 26px; - right: -12px; - background: #F7F8F9; - box-shadow: 0 0 2px 0 rgba(4, 39, 60, 0.12), 0 2px 2px 0 rgba(4, 39, 60, 0.24); - border-radius: 2px; - opacity: 0; - pointer-events: none; - transition: opacity 100ms ease-in; - - /* Make sure children inherit border radius so they don't bleed over */ - & > *:first-child { - border-top-right-radius: inherit; - border-top-left-radius: inherit; - } - - & > *:last-child { - border-bottom-right-radius: inherit; - border-bottom-left-radius: inherit; - } - - /* Carrot on top of menu */ - &::before, - &::after { - content: ''; - position: absolute; - display: block; - right: 12px; - width: 0; - height: 0; - border-style: solid; - border-width: 0 6px 6px 6px; - } - - &::before { - top: -7px; - border-color: transparent transparent rgba(4, 39, 60, 0.06) transparent; - } - - &::after { - top: -6px; - border-color: transparent transparent #F7F8F9 transparent; - } -} - -.menuButton { - padding: 7px 24px; - font-size: 16px; - color: #3F5167; - line-height: 22px; - white-space: nowrap; - transition: background 100ms ease-in; - - &.menuButtonDanger { - color: #EB3E46; - } - - &:hover { - background: #E0E4E7; - } -} - -.history { - cursor: pointer; - font-family: HelveticaNeue; - font-size: 12px; - color: #3F5167; - line-height: 16px; - white-space: nowrap; - - .historyClose { - display: inline-block; - vertical-align: middle; - width: 14px; - height: 14px; - margin: -3px 12px 0 0; - transform: rotate(-45deg); - - svg { - width: inherit; - height: inherit; - fill: #22B8EB; - transition: fill 300ms ease-out; - } - } - - &:hover, - &:focus { - text-decoration: underline; - - svg { - fill: #13a3d4; - } - } -} diff --git a/app/scripts/components/repo/repoSettings/webhooks/Pipeline/Options.jsx b/app/scripts/components/repo/repoSettings/webhooks/Pipeline/Options.jsx deleted file mode 100644 index 4ddaa7d1e6..0000000000 --- a/app/scripts/components/repo/repoSettings/webhooks/Pipeline/Options.jsx +++ /dev/null @@ -1,68 +0,0 @@ -'use strict'; -import React, { Component, PropTypes } from 'react'; -import { VelocityTransitionGroup } from 'velocity-react'; -// Some issues getting InlineSVG loaded -const InlineSVG = require('svg-inline-react'); - -import styles from './Options.css'; - -export default class PipelineOptions extends Component { - static propTypes = { - isActive: PropTypes.bool.isRequired, - toggleHistory: PropTypes.func.isRequired, - delete: PropTypes.func.isRequired - } - - renderMenu() { - return ( -
    -
    -
    - View history -
    -
    - Delete -
    -
    -
    - ); - } - - renderHistory() { - return ( -
    -
    - -
    - Hide history -
    - ); - } - - render() { - return ( -
    - { this.props.isActive ? this.renderHistory() : this.renderMenu() } -
    - ); - } -} diff --git a/app/scripts/components/repo/repoSettings/webhooks/Pipeline/Status.css b/app/scripts/components/repo/repoSettings/webhooks/Pipeline/Status.css deleted file mode 100644 index 4949092777..0000000000 --- a/app/scripts/components/repo/repoSettings/webhooks/Pipeline/Status.css +++ /dev/null @@ -1,26 +0,0 @@ -.status { - font-size: 12px; - line-height: 16px; - color: #7A8491; - text-transform: uppercase; - - &.clickable { - cursor: pointer; - - &:hover { - text-decoration: underline; - } - } - - i { - margin-right: 5px; - } - - &.status_success { - color: #67CFC0; - } - - &.status_error { - color: #EB3E46; - } -} diff --git a/app/scripts/components/repo/repoSettings/webhooks/Pipeline/Status.jsx b/app/scripts/components/repo/repoSettings/webhooks/Pipeline/Status.jsx deleted file mode 100644 index 88b8c2c7f4..0000000000 --- a/app/scripts/components/repo/repoSettings/webhooks/Pipeline/Status.jsx +++ /dev/null @@ -1,56 +0,0 @@ -'use strict'; -import React, { Component, PropTypes } from 'react'; -import FA from 'common/FontAwesome'; - -import styles from './Status.css'; - -export default class Status extends Component { - static propTypes = { - status: PropTypes.oneOf(['init', 'pending', 'success', 'error', 'failure']), - onClick: PropTypes.func - } - - render() { - const klasses = [styles.status]; - - if (this.props.onClick) { - klasses.push(styles.clickable); - } - - let icon, status; - - switch(this.props.status) { - case 'init': - case 'pending': - icon = ; - status = 'pending'; - break; - case 'success': - icon = ; - status = 'success'; - break; - case 'error': - case 'failure': - icon = ; - status = 'error'; - break; - default: - icon = ; - status = 'unknown'; - break; - } - - klasses.push(styles[`status_${status}`]); - - return ( -
    - {icon} - {status} -
    - ); - } -} diff --git a/app/scripts/components/repo/repoSettings/webhooks/Pipeline/index.css b/app/scripts/components/repo/repoSettings/webhooks/Pipeline/index.css deleted file mode 100644 index 15e3ca2970..0000000000 --- a/app/scripts/components/repo/repoSettings/webhooks/Pipeline/index.css +++ /dev/null @@ -1,80 +0,0 @@ -.pipeline { - margin: 40px 0; - padding: 32px; - background: #FBFBFC; - border: 1px solid #C4CDDA; - border-radius: 2px; - transition: opacity 140ms ease-in; - - &:first-child { - margin-top: 24px; - } - - &:last-child { - margin-bottom: 0; - } - - &.pipeline_deleting { - opacity: 0.5; - pointer-events: none; - } -} - -.overview { - display: flex; - justify-content: space-between; - align-items: center; - margin: 0 -16px; - - /* Set spacing rhythm */ - & > * { - margin-right: 16px; - margin-left: 16px; - } -} - -.icon { - /* Use content box-sizing to allow children to inherit content dimensions */ - box-sizing: content-box; - display: flex; - justify-content: center; - align-items: center; - padding: 4px; - width: 38px; - height: 38px; - - /* Inherit dimensions of parent */ - & > i, - & > i > svg { - width: inherit; - height: inherit; - } - - & > img { - max-width: 32px; - max-height: 32px; - min-width: 16px; - min-height: 16px; - } -} - -.summaryDetails { - flex: 1; - - .name { - font-size: 18px; - color: #3F5167; - line-height: 24px; - } - - .url { - font-size: 12px; - color: #7A8491; - line-height: 16px; - overflow-wrap: break-word; - word-wrap: break-word; - -ms-word-break: break-all; - word-break: break-all; - word-break: break-word; - } -} diff --git a/app/scripts/components/repo/repoSettings/webhooks/Pipeline/index.jsx b/app/scripts/components/repo/repoSettings/webhooks/Pipeline/index.jsx deleted file mode 100644 index 9eb3fe1179..0000000000 --- a/app/scripts/components/repo/repoSettings/webhooks/Pipeline/index.jsx +++ /dev/null @@ -1,147 +0,0 @@ -'use strict'; -import React, { Component, PropTypes } from 'react'; -// Some issues getting InlineSVG loaded -const InlineSVG = require('svg-inline-react'); - -import connectToStores from 'fluxible-addons-react/connectToStores'; -import deletePipeline from 'actions/deletePipeline'; -import PipelineHistoryStore from 'stores/PipelineHistoryStore'; -import JWTStore from 'stores/JWTStore'; -import { VelocityTransitionGroup } from 'velocity-react'; - -import Options from './Options.jsx'; -import History from './History.jsx'; - -import styles from './index.css'; - -class Pipeline extends Component { - static propTypes = { - isActive: PropTypes.bool.isRequired, - name: PropTypes.string.isRequired, - namespace: PropTypes.string.isRequired, - results: PropTypes.object, - pipeline: PropTypes.shape({ - created: PropTypes.string.isRequired, - expectFinalCallback: PropTypes.bool.isRequired, - lastUpdated: PropTypes.string.isRequired, - slug: PropTypes.string.isRequired, - webhooks: PropTypes.arrayOf(PropTypes.shape({ - created: PropTypes.string, - hookUrl: PropTypes.string.isRequired, - lastUpdated: PropTypes.string, - name: PropTypes.string - })) - }) - } - - static contextTypes = { - executeAction: PropTypes.func.isRequired - } - - constructor(props) { - super(props); - this.state = this._getInitialState(props); - this.toggleHistory = this._toggleHistory.bind(this); - this.deletePipeline = this._deletePipeline.bind(this); - } - - _getInitialState(props) { - return { - deleting: false, - isActive: this.props.isActive - }; - } - - _toggleHistory() { - this.setState({isActive: !this.state.isActive}); - } - - _deletePipeline() { - this.setState({deleting: true}); - const { JWT: jwt, namespace, name, pipeline: { slug } } = this.props; - this.context.executeAction(deletePipeline, { - jwt, namespace, name, slug - }); - } - - possiblyRenderHistory() { - if (!this.state.isActive) { - return undefined; - } - - const attempts = this.props.results[this.props.pipeline.slug]; - console.log(attempts); // eslint-disable-line - return ( - - ); - } - - render() { - const pipelineClasses = [styles.pipeline]; - - if (this.state.deleting) { - pipelineClasses.push(styles.pipeline_deleting); - } - - const latestAttempt = this.props.results.length && this.props.results[0]; - - return ( -
    -
    -
    - -
    -
    -
    - {this.props.pipeline.name} -
    -
    - {this.props.pipeline.webhooks[0].hookUrl} -
    -
    - -
    - - { this.possiblyRenderHistory() } - -
    - ); - } -} - -export default connectToStores( - Pipeline, - [ - PipelineHistoryStore, - JWTStore - ], - ({ getStore }, props) => { - const { results } = getStore(PipelineHistoryStore).getState(); - const { jwt } = getStore(JWTStore).getState(); - return { - results, - JWT: jwt - }; - }); diff --git a/app/scripts/components/repo/repoSettings/webhooks/Pipelines.jsx b/app/scripts/components/repo/repoSettings/webhooks/Pipelines.jsx deleted file mode 100644 index c1f9991311..0000000000 --- a/app/scripts/components/repo/repoSettings/webhooks/Pipelines.jsx +++ /dev/null @@ -1,61 +0,0 @@ -'use strict'; -import React, { Component, PropTypes } from 'react'; -import ReactDOM from 'react-dom'; -import { VelocityTransitionGroup } from 'velocity-react'; - -const debug = require('debug')('Webhooks'); - -import Pipeline from './Pipeline/index.jsx'; - -export default class Pipelines extends Component { - static propTypes = { - activeSlug: PropTypes.string, - name: PropTypes.string.isRequired, - namespace: PropTypes.string.isRequired, - pipelines: PropTypes.arrayOf(PropTypes.shape({ - created: PropTypes.string.isRequired, - expectFinalCallback: PropTypes.bool.isRequired, - lastUpdated: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - slug: PropTypes.string.isRequired, - webhooks: PropTypes.arrayOf(PropTypes.shape({ - created: PropTypes.string, - hookUrl: PropTypes.string.isRequired, - lastUpdated: PropTypes.string, - name: PropTypes.string - })) - })) - } - - renderPipeline(pipeline) { - return ( - - ); - } - - render() { - return ( -
    - - { this.props.pipelines.map(this.renderPipeline.bind(this)) } - -
    - ); - } -} diff --git a/app/scripts/components/repo/repoSettings/webhooks/WebhooksTutorial.css b/app/scripts/components/repo/repoSettings/webhooks/WebhooksTutorial.css deleted file mode 100644 index 55308c2c11..0000000000 --- a/app/scripts/components/repo/repoSettings/webhooks/WebhooksTutorial.css +++ /dev/null @@ -1,74 +0,0 @@ -.tutorial { - margin-top: 8px; - text-align: center; -} - -.headline { - margin: 12px 0; - font-size: 14px; - color: #3F5167; - text-transform: uppercase; -} - -.addWebhook { - display: block; - width: 100%; - margin: 12px 0; - padding: 15px; - height: 52px; - background: #FBFBFC; - border: 1px solid #22B8EB; - border-radius: 2px; - transition-duration: 240ms; - - .webhookIcon, - .plusIcon { - position: absolute; - left: 50%; - top: 15px; - height: 22px; - transition: opacity 240ms 10ms ease-out; - } - - .webhookIcon { - width: 73px; - margin-left: calc(73px/-2); - - svg { - width: 73px; - height: 22px; - } - } - - .plusIcon { - width: 22px; - margin-left: -11px; - opacity: 0; - - svg { - width: 22px; - height: 22px; - fill: #FBFBFC; - } - } - - &:hover { - .webhookIcon { - opacity: 0; - } - - .plusIcon { - opacity: 1; - } - } -} - -.details { - position: relative; - margin: 12px auto; - max-width: 330px; - font-style: italic; - font-size: 12px; - color: #7A8491; - line-height: 16px; -} diff --git a/app/scripts/components/repo/repoSettings/webhooks/WebhooksTutorial.jsx b/app/scripts/components/repo/repoSettings/webhooks/WebhooksTutorial.jsx deleted file mode 100644 index 52cd4e5236..0000000000 --- a/app/scripts/components/repo/repoSettings/webhooks/WebhooksTutorial.jsx +++ /dev/null @@ -1,38 +0,0 @@ -'use strict'; -import React, { Component, PropTypes } from 'react'; -const { func } = PropTypes; - -// Some issues getting InlineSVG loaded -const InlineSVG = require('svg-inline-react'); - -import styles from './WebhooksTutorial.css'; - -export default class WebhooksTutorial extends Component { - static propTypes = { - addWebhook: func.isRequired - } - render() { - return ( -
    -

    Create a Webhook

    - -

    - A webhook is an HTTP call-back triggered by a specific event. - You can create a single webhook to start and connect multiple - webhooks to further build out your workflow. -

    -
    - ); - } -} diff --git a/app/scripts/components/repo/repoSettings/webhooks/imagePush.svg b/app/scripts/components/repo/repoSettings/webhooks/imagePush.svg deleted file mode 100644 index d03a7c31d8..0000000000 --- a/app/scripts/components/repo/repoSettings/webhooks/imagePush.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/app/scripts/components/repo/repoSettings/webhooks/index.css b/app/scripts/components/repo/repoSettings/webhooks/index.css deleted file mode 100644 index db184f3fd4..0000000000 --- a/app/scripts/components/repo/repoSettings/webhooks/index.css +++ /dev/null @@ -1,164 +0,0 @@ -.wrap { - margin: 24px 0; - lost-center: 1260px; - background: #FCFDFF; - border: 1px solid #C4CDDA; - border-radius: 4px; - - a { - color: #22B8EB; - text-decoration: none; - cursor: pointer; - - &:hover { - color: #13A3D4; - text-decoration: underline; - } - } -} - -.header { - lost-column: 1; - padding: 9px 20px; - background: rgba(230,237,243,0.50); - border-bottom: 1px solid #C4CDDA; - border-radius: 4px 4px 0 0; - font-size: 18px; - color: #3F5167; - line-height: 24px; -} - -.leftColumn { - lost-column: 1/4; - position: relative; - padding: 20px 38px 20px 20px; - min-height: 200px; - background: #FBFBFC; - border-right: 1px solid #C4CDDA; - border-radius: 0 0 4px 4px; - - &::before, - &::after { - content: ''; - display: block; - position: absolute; - top: 78px; - width: 0; - height: 0; - border-style: solid; - border-width: 24px 0 24px 18px; - } - - &::before { - right: -19px; - border-color: transparent transparent transparent #C4CDDA; - } - - &::after { - right: -18; - border-color: transparent transparent transparent #FBFBFC; - } -} - -.rightColumn { - lost-column: 3/4; - padding: 20px 20px 20px 30px; -} - -.segmentHeader { - margin-bottom: 10px; - font-size: 12px; - color: #7A8491; - line-height: 16px; - text-transform: uppercase; -} - -.event { - display: block; - margin-top: 45px; - - .eventTitle { - display: flex; - align-items: center; - font-size: 18px; - color: #3F5167; - line-height: 24px; - - i { - flex-shrink: 1; - display: block; - width: 56px; - height: 43px; - margin-right: 12px; - - svg { - width: 100%; - height: 100%; - stroke: #7A8491; - } - } - } - - .eventDescription { - margin-top: 32px; - max-width: 210px; - font-size: 12px; - color: #3F5167; - line-height: 16px; - } -} - -.addWebHook { - display: inline-block; - vertical-align: middle; - padding: 0; - width: 14px; - height: 14px; - background-color: transparent; - border-color: transparent; - padding: 0; - margin: -3px 0 0 12px; - transition: transform 120ms ease-out; - - &:hover, - &:focus, - &:active { - border-color: transparent; - background-color: transparent; - outline: none; - } - - svg { - width: inherit; - height: inherit; - fill: #22B8EB; - transition: fill 300ms ease-out; - } - - &:hover svg, - &:focus svg { - fill: #13a3d4; - } -} - -.addWebHook_rotated { - transform: rotate(-45deg); -} - -.transitionEnter { - opacity: 0; - - &.transitionEnterActive { - opacity: 1; - transition: opacity 240ms ease-in; - } -} - -.transitionLeave { - opacity: 1; - - &.transitionLeaveActive { - opacity: 0; - transition: opacity 100ms ease-in; - } -} diff --git a/app/scripts/components/repo/repoSettings/webhooks/index.jsx b/app/scripts/components/repo/repoSettings/webhooks/index.jsx deleted file mode 100644 index 7a98a84055..0000000000 --- a/app/scripts/components/repo/repoSettings/webhooks/index.jsx +++ /dev/null @@ -1,204 +0,0 @@ -'use strict'; - -import React, { - PropTypes, - createClass, - Component, - cloneElement -} from 'react'; - -import find from 'lodash/collection/find'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import { VelocityTransitionGroup } from 'velocity-react'; -// Some issues getting InlineSVG loaded -const InlineSVG = require('svg-inline-react'); - -import WebhooksSettingsStore from 'stores/WebhooksSettingsStore'; - -import AddWebhookForm from './AddWebhookForm'; -import WebhooksTutorial from './WebhooksTutorial'; -import Pipelines from './Pipelines'; - -const debug = require('debug')('webhooks'); -import styles from './index.css'; - -class WebhooksSettings extends Component { - static propTypes = { - history: PropTypes.object.isRequired, - pipelines: PropTypes.arrayOf(PropTypes.shape({ - created: PropTypes.string.isRequired, - expectFinalCallback: PropTypes.bool.isRequired, - lastUpdated: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - slug: PropTypes.string.isRequired, - webhooks: PropTypes.arrayOf(PropTypes.shape({ - created: PropTypes.string, - hookUrl: PropTypes.string.isRequired, - lastUpdated: PropTypes.string, - name: PropTypes.string - })) - })) - } - - state = { - showForm: false - } - - toggleAddWebhookForm() { - this.setState({showForm: !this.state.showForm}); - } - - hideAddWebhookForm() { - this.setState({showForm: false}); - } - - showAddWebhookForm() { - this.setState({showForm: true}); - } - - renderToggleFormButton() { - const klasses = [styles.addWebHook]; - let title; - - if (this.state.showForm) { - klasses.push(styles.addWebHook_rotated); - title = 'Hide form'; - } else { - title = 'Add new webhook'; - } - - return ( - - ); - } - - possiblyRenderTutorial() { - if (this.state.showForm || - (this.props.pipelines && this.props.pipelines.length)) { - return undefined; - } - - return ( - - ); - } - - possiblyRenderTutorialOrForm() { - let form, tutorial; - - if (this.state.showForm) { - const { namespace, name } = this.props; - form = ( - - ); - } else if (!(this.props.pipelines && this.props.pipelines.length)) { - tutorial = ( - - ); - } - - // We only want to transition the form if there are pipelines - // It looks weird otherwise to swap the form and tutorial with slides - if (this.props.pipelines && this.props.pipelines.length) { - return ( -
    - - { form } - - { tutorial } -
    - ); - } else { - return ( -
    - { form } - { tutorial } -
    - ); - } - } - - possiblyRenderPipelines() { - if (!this.props.pipelines || !this.props.pipelines.length) { - return undefined; - } - - return ( - - ); - } - - render() { - return ( -
    -
    Workflows
    -
    -
    Trigger Event
    - -
    - - Image Pushed -
    -

    - When an image is pushed to this repo, - your workflows will kick off based on - your specified webhooks.  - - Learn More - -

    -
    -
    -
    -
    - Web Hooks - { this.renderToggleFormButton() } -
    - { this.possiblyRenderTutorialOrForm() } - { this.possiblyRenderPipelines() } -
    -
    - ); - } -} - -export default connectToStores( - WebhooksSettings, - [WebhooksSettingsStore], - ({ getStore }, props) => getStore(WebhooksSettingsStore).getState() -); diff --git a/app/scripts/components/repo/repoSettings/webhooks/plus.svg b/app/scripts/components/repo/repoSettings/webhooks/plus.svg deleted file mode 100644 index e4f2c6f9b4..0000000000 --- a/app/scripts/components/repo/repoSettings/webhooks/plus.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/app/scripts/components/repo/repoSettings/webhooks/webhook.svg b/app/scripts/components/repo/repoSettings/webhooks/webhook.svg deleted file mode 100644 index d714eb8e3e..0000000000 --- a/app/scripts/components/repo/repoSettings/webhooks/webhook.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/app/scripts/components/repo/repo_details/BuildDetails.css b/app/scripts/components/repo/repo_details/BuildDetails.css deleted file mode 100644 index f03141bc02..0000000000 --- a/app/scripts/components/repo/repo_details/BuildDetails.css +++ /dev/null @@ -1,5 +0,0 @@ -.buildCode { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} \ No newline at end of file diff --git a/app/scripts/components/repo/repo_details/BuildDetails.jsx b/app/scripts/components/repo/repo_details/BuildDetails.jsx deleted file mode 100644 index ab88dcbe6e..0000000000 --- a/app/scripts/components/repo/repo_details/BuildDetails.jsx +++ /dev/null @@ -1,96 +0,0 @@ -'use strict'; -import React, { PropTypes, Component } from 'react'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import RepoDetailsBuildsStore from '../../../stores/RepoDetailsBuildsStore'; -import BuildStatus from './BuildStatus'; -import SourceRepositoryCard from 'common/SourceRepositoryCard'; -import moment from 'moment'; -import trunc from 'lodash/string/trunc'; -import { - FlexTable, - FlexHeader, - FlexRow, - FlexItem -} from 'common/FlexTable'; -const { func } = PropTypes; -import styles from './BuildDetails.css'; -const debug = require('debug')('RepositoryDetailsTags'); - -class TableItem extends Component { - - _formatDate(ISODateString) { - return ISODateString ? moment(ISODateString, moment.ISO_8601).fromNow() : ''; - } - - renderBuildStatus() { - return ( - - - - ); - } - - showBuildLogs = (e) => { - const { build_code, params, history } = this.props; - const { user, splat } = params; - history.pushState(null, `/r/${user}/${splat}/builds/${build_code}/`); - }; - - render() { - debug(this.props); - const { created_date, last_updated, dockertag_name } = this.props; - return ( - - - {this.renderBuildStatus()} - - {dockertag_name} - {this._formatDate(created_date)} - {this._formatDate(last_updated)} - - ); - } -} - -class BuildDetails extends Component { - - _mkItem = (item) => { - return ( - - ); - } - - render() { - const { provider, repo_web_url } = this.props.autoBuildStore; - return ( -
    -
    -
    - - - Status - Tag - Created - Last Updated - - {this.props.results.map(this._mkItem)} - -
    -
    -
    - -
    -
    - ); - } -} - -export default connectToStores(BuildDetails, - [RepoDetailsBuildsStore], - function({ getStore }, props) { - return getStore(RepoDetailsBuildsStore).getState(); - }); diff --git a/app/scripts/components/repo/repo_details/BuildLogs.css b/app/scripts/components/repo/repo_details/BuildLogs.css deleted file mode 100644 index 1ccb5b3b17..0000000000 --- a/app/scripts/components/repo/repo_details/BuildLogs.css +++ /dev/null @@ -1,8 +0,0 @@ -.logs { - white-space: pre; - font-family: monospace; - overflow-x: scroll; -} -.buildCode { - margin: 0; -} \ No newline at end of file diff --git a/app/scripts/components/repo/repo_details/BuildLogs.jsx b/app/scripts/components/repo/repo_details/BuildLogs.jsx deleted file mode 100644 index d245cda496..0000000000 --- a/app/scripts/components/repo/repo_details/BuildLogs.jsx +++ /dev/null @@ -1,117 +0,0 @@ -'use strict'; -import React, { PropTypes, Component } from 'react'; -import { Link } from 'react-router'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import Card, { Block } from '@dux/element-card'; -import Code from 'common/Code'; -import Markdown from '@dux/element-markdown'; -import RepoDetailsBuildLogsStore from 'stores/RepoDetailsBuildLogs'; -import endsWith from 'lodash/string/endsWith'; -import moment from 'moment'; -import { - FlexTable, - FlexHeader, - FlexItem, - FlexRow -} from 'common/FlexTable'; -import { - FlexTable as Table, - Row, - Header, - Item -} from 'common/TagsFlexTable'; -import styles from './BuildLogs.css'; -const debug = require('debug')('BuildLogs'); - - var status = { - '-2': 'exception', - '-1': 'error', - 0: 'pending', - 1: 'claimed', - 2: 'started', - 3: 'cloned', - 4: 'readme', - 5: 'dockerfile', - 6: 'built', - 7: 'bundled', - 8: 'uploaded', - 9: 'pushed', - 10: 'done' - }; - -class BuildLogs extends Component { - - _formatDate(ISODateString) { - //TODO: Remove this if statement once Highland 2.0 works for prod - //fixes a bug where Highland returns a date without the `Z` UTC indicator - //only in build logs on prod - if (!endsWith(ISODateString, 'Z')) { - return ISODateString ? moment(`${ISODateString}Z`, moment.ISO_8601).fromNow() : ''; - } - return ISODateString ? moment(ISODateString, moment.ISO_8601).fromNow() : ''; - } - - render() { - const { - failure, - readme_contents, - created_at, - build_path, - docker_tag, - build_code, - dockerfile_contents, - source_branch, - logs - } = this.props.build_results; - - let failureAlert = null; - if(failure) { - failureAlert =
    {failure}
    ; - } - return ( -
    - {failureAlert} - -
    - SourceRef - Dockerfile Location - Docker Tag - Build Created - UTC -
    - - {source_branch} - {build_path} - {docker_tag} - {this._formatDate(created_at)} - {created_at} - -
    - - -

    {build_code}

    -
    -
    - - - {readme_contents} - - - - {dockerfile_contents} - - - -

    {logs}

    -
    -
    -
    - ); - } -} - -export default connectToStores(BuildLogs, - [RepoDetailsBuildLogsStore], - function({ getStore }, props) { - return getStore(RepoDetailsBuildLogsStore).getState(); - }); diff --git a/app/scripts/components/repo/repo_details/BuildStatus.css b/app/scripts/components/repo/repo_details/BuildStatus.css deleted file mode 100644 index c0eb045cc3..0000000000 --- a/app/scripts/components/repo/repo_details/BuildStatus.css +++ /dev/null @@ -1,20 +0,0 @@ -@import "dux/css/colors.css"; - -.statusWrapper { - cursor: pointer; -} - -.warning { - composes: statusWrapper; - color: var(--warning-color); -} - -.success { - composes: statusWrapper; - color: var(--success-color); -} - -.primary { - composes: statusWrapper; - color: var(--primary-color); -} \ No newline at end of file diff --git a/app/scripts/components/repo/repo_details/BuildStatus.jsx b/app/scripts/components/repo/repo_details/BuildStatus.jsx deleted file mode 100644 index 2be1a661cc..0000000000 --- a/app/scripts/components/repo/repo_details/BuildStatus.jsx +++ /dev/null @@ -1,81 +0,0 @@ -'use strict'; -import React, { PropTypes, Component } from 'react'; -import FA from 'common/FontAwesome'; -import styles from './BuildStatus.css'; -const { number } = PropTypes; - -/** - * possible build status codes - * -2: 'exception', - * -1: 'error', - * 0: 'pending', - * 1: 'claimed', - * 2: 'started', - * 3: 'cloned', - * 4: 'readme', - * 5: 'dockerfile', - * 6: 'built', - * 7: 'bundled', - * 8: 'uploaded', - * 9: 'pushed', - * 10: 'done', - * 11: 'queued' - */ - -export default class BuildStatus extends Component { - static propTypes = { - status: number.isRequired - }; - - render() { - const { status } = this.props; - - switch (status) { - case -2: - case -1: - return ( - - Error - - ); - case 0: - case 1: - case 11: - return ( - - Queued - - ); - case 2: - case 3: - case 4: - case 5: - return ( - - Building - - ); - case 6: - case 7: - case 8: - case 9: - return ( - - Building - - ); - case 10: - return ( - - Success - - ); - default: - return ( - - Unknown - - ); - } - } -} diff --git a/app/scripts/components/repo/repo_details/Dockerfile.css b/app/scripts/components/repo/repo_details/Dockerfile.css deleted file mode 100644 index ae30aeb782..0000000000 --- a/app/scripts/components/repo/repo_details/Dockerfile.css +++ /dev/null @@ -1,3 +0,0 @@ -.dockerfile { - overflow-x: auto; -} diff --git a/app/scripts/components/repo/repo_details/Dockerfile.jsx b/app/scripts/components/repo/repo_details/Dockerfile.jsx deleted file mode 100644 index 02c07643d6..0000000000 --- a/app/scripts/components/repo/repo_details/Dockerfile.jsx +++ /dev/null @@ -1,41 +0,0 @@ -'use strict'; - -import React, { PropTypes, Component } from 'react'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import Card, { Block } from '@dux/element-card'; -import SourceRepositoryCard from 'common/SourceRepositoryCard'; -import RepoDetailsDockerfileStore from '../../../stores/RepoDetailsDockerfileStore'; -var debug = require('debug')('Dockerfile'); -import styles from './Dockerfile.css'; -import Code from 'common/Code'; - -class Dockerfile extends Component { - - static propTypes = { - dockerfile: PropTypes.string.isRequired - } - - render() { - const { provider, repo_web_url } = this.props.autoBuildStore; - return ( -
    -
    - - {this.props.dockerfile} - -
    -
    - -
    -
    - ); - } -} - -export default connectToStores(Dockerfile, - [ - RepoDetailsDockerfileStore - ], - function({ getStore }, props) { - return getStore(RepoDetailsDockerfileStore).getState(); - }); diff --git a/app/scripts/components/repo/repo_details/Info.jsx b/app/scripts/components/repo/repo_details/Info.jsx deleted file mode 100644 index bd366eaa03..0000000000 --- a/app/scripts/components/repo/repo_details/Info.jsx +++ /dev/null @@ -1,75 +0,0 @@ -'use strict'; - -import React, { PropTypes, Component } from 'react'; -import RepoShortDescription from './info/RepoShortDescription.jsx'; -import RepoFullDescription from './info/RepoFullDescription.jsx'; -import SourceRepositoryCard from 'common/SourceRepositoryCard'; -import PullCommand from './info/PullCommand.jsx'; -import Owner from './info/Owner.jsx'; -import Comments from './info/Comments.jsx'; -const { string, shape, object, bool, number } = PropTypes; - -const debug = require('debug')('RepositoryDetailsInfo'); - - -export default class RepositoryDetailsInfo extends Component { - static propTypes = { - description: string.isRequired, - fullDescription: string.isRequired, - isPrivate: bool.isRequired, - isAutomated: bool.isRequired, - name: string.isRequired, - namespace: string.isRequired, - status: number.isRequired, - user: object, - JWT: string, - canEdit: bool, - autoBuildStore: shape({ - provider: string.isRequired, - repo_web_url: string.isRequired - }) - } - - render() { - const { - namespace, - name, - isAutomated, - JWT, - user - } = this.props; - const { provider, repo_web_url } = this.props.autoBuildStore; - - const pullCommandCard = ; - const ownerCard = ; - let sourceCard = null; - if (isAutomated) { - sourceCard = ; - } - - return ( -
    -
    -
    - - -
    -
    - {pullCommandCard} - {ownerCard} - {sourceCard} -
    -
    -
    -
    - -
    -
    -
    - ); - } - -} diff --git a/app/scripts/components/repo/repo_details/ScannedTag.css b/app/scripts/components/repo/repo_details/ScannedTag.css deleted file mode 100644 index d577917f10..0000000000 --- a/app/scripts/components/repo/repo_details/ScannedTag.css +++ /dev/null @@ -1,8 +0,0 @@ -.scanTitle { - font-size: 1.2rem; -} - -/* add extra padding so that borders work */ -.wrapper { - padding: 0.5rem; -} diff --git a/app/scripts/components/repo/repo_details/ScannedTag.jsx b/app/scripts/components/repo/repo_details/ScannedTag.jsx deleted file mode 100644 index 08accb3303..0000000000 --- a/app/scripts/components/repo/repo_details/ScannedTag.jsx +++ /dev/null @@ -1,124 +0,0 @@ -'use strict'; - -import React, { PropTypes, Component } from 'react'; -import Card, { Block } from '@dux/element-card'; -import { connect } from 'react-redux'; -import { createSelector, createStructuredSelector } from 'reselect'; -import { - getComponents, - getComponentsBySeverity, - getLayers, - getScan, - getVulnerabilities, - getVulnerabilitiesByLayer -} from './scannedTag/selectors'; -import { ERROR } from 'reduxConsts'; -import forEach from 'lodash/collection/forEach'; -import ScanHeader from './scannedTag/ScanHeader.jsx'; -import Layer from './scannedTag/Layer.jsx'; -import styles from './ScannedTag.css'; -import { Map } from 'immutable'; -import { getStatus } from 'selectors/status'; - -const { object, array, instanceOf, shape } = PropTypes; - -// TODO: conversion to records -// Right now we're storing only *one* scan in the reducer, therefore all entities -// can be merged in to the scan as we know they all belong to this scan. -// -// This produces a denormalized, nested scan with all entities as the child of the scan. -const getFullScan = createSelector( - [getScan, getLayers, getComponents, getVulnerabilities], - (scan, layers, components, vulns) => ({ - ...scan, - layers, - components, - vulnerabilities: vulns - }) -); - -let mapState = createStructuredSelector({ - componentsBySeverity: getComponentsBySeverity, - scan: getFullScan, - status: getStatus, - vulnerabilitiesByLayer: getVulnerabilitiesByLayer -}); - -/** - * This component is the detail view of particular scan/tag combination, showing - * vulnerability and component information for a tag. - */ -@connect(mapState) -export default class ScannedTag extends Component { - - static propTypes = { - componentsBySeverity: shape({ - critical: array, - major: array, - minor: array, - secure: array - }), - scan: object, - status: instanceOf(Map), - vulnerabilitiesByLayer: object - } - - mkLayer = (layerIndex) => { - const { scan, vulnerabilitiesByLayer } = this.props; - const layer = scan.layers[layerIndex]; - const layerVulnerabilities = vulnerabilitiesByLayer[layerIndex]; - let layerComponents = {}; - //layer.components is an array with ids - forEach(layer.components, c => { - layerComponents[c] = scan.components[c]; - }); - return ( - - ); - }; - - render() { - const { - componentsBySeverity, - params, - namespace, - scan, - status, - vulnerabilitiesByLayer - } = this.props; - const { blobs, reponame, tag, scan_id } = scan; - //TODO change to use redux-simple-router params when we include it - const ns = namespace ? namespace : params.user; - const rn = reponame ? reponame : params.splat; - const tn = tag ? tag : params.tagname; - //No scan_id ==> first scan has failed or is in progress - const scanError = !blobs || !scan_id; - if (status.getIn(['getScanForTag', ns, rn, tn, 'status']) === ERROR || scanError) { - return ( - - -
    Scan results unavailable.
    -
    -
    - ); - } - const layerInfo = {`${reponame}:${tag}`}; - // blobs is an ordered array of layer ids, so we must use that to preserve API ordering - return ( - Scan results for {layerInfo}}> - -
    - - {blobs.map(this.mkLayer)} -
    -
    -
    - ); - } -} diff --git a/app/scripts/components/repo/repo_details/Tags.css b/app/scripts/components/repo/repo_details/Tags.css deleted file mode 100644 index 64cc8c458b..0000000000 --- a/app/scripts/components/repo/repo_details/Tags.css +++ /dev/null @@ -1,36 +0,0 @@ -@import "dux/css/colors.css"; - -.cardHeader { - font-size: 1.2rem; -} - -.secondaryTableHeader { - font-weight: 500; - font-size: 0.9rem; - padding: 0.4rem 0; -} - -.empty { - font-size: 1.25rem; - font-weight: 300; - color: var(--secondary-3); -} - -.inlineBlock { - display: inline-block; -} - -.questionMark { - composes: inlineBlock; - color: #C4CDD9; - cursor: pointer; - font-size: 1.2rem; -} - -.tooltipTitle { - font-weight: 500; -} - -.toggleButtonWrapper { - text-align: center; -} diff --git a/app/scripts/components/repo/repo_details/Tags.jsx b/app/scripts/components/repo/repo_details/Tags.jsx deleted file mode 100644 index da20e5bd8e..0000000000 --- a/app/scripts/components/repo/repo_details/Tags.jsx +++ /dev/null @@ -1,212 +0,0 @@ -'use strict'; -import React, { PropTypes, Component } from 'react'; -const { array, object, bool, string, number, shape, func } = PropTypes; -import { connect } from 'react-redux'; -import Card, { Block } from '@dux/element-card'; - -import { FlexTable, FlexRow, FlexHeader, FlexItem } from 'common/FlexTable.jsx'; -import ScannedTagRow from './tags/ScannedTagRow.jsx'; -import UnscannedTagRow from './tags/UnscannedTagRow.jsx'; -import styles from './Tags.css'; -import FontAwesome from 'common/FontAwesome'; -import Tooltip from 'rc-tooltip'; -import { createStructuredSelector } from 'reselect'; -import { - getScannedTags, - getScannedTagCount, - getUnscannedTags, - getUnscannedTagCount -} from './tags/selectors'; -import { getStatus } from 'selectors/status'; -import * as tagActions from 'actions/redux/tags.js'; -import { mapActions } from 'reduxUtils'; -import Button from '@dux/element-button'; -import { StatusRecord } from 'records'; -import moment from 'moment'; - -const debug = require('debug')('RepositoryDetailsTags'); - -const mapState = createStructuredSelector({ - scannedTags: getScannedTags, - scannedTagCount: getScannedTagCount, - unscannedTags: getUnscannedTags, - unscannedTagCount: getUnscannedTagCount, - status: getStatus -}); - -/** - * TagDisplay is the new UI for listing tags with vulnerability information from - * nautilus. - * It connects to the redux store and uses redux actions. - */ -@connect(mapState, mapActions(tagActions)) -class TagDisplay extends Component { - - static propTypes = { - actions: shape({ - deleteRepoTag: func - }), - status: object, - - scannedTags: array, - scannedTagCount: number, - unscannedTags: array, - unscannedTagCount: number - } - - state = { - //one of 'unknown', 'show' - showUnscannedTags: 'unknown' - } - - toggleShowUnscannedTags = (e) => { - const { showUnscannedTags } = this.state; - //will be 'unknown' on the first time clicking Show Outdated Tags - this.setState({ - showUnscannedTags: 'show' - }); - } - - mkUnscannedTagRow = (tag) => { - const { status } = this.props; - const tagName = tag.name; - const tagStatus = status.getIn(['deleteRepoTag', tagName], new StatusRecord()); - return ( - - ); - } - - mkUnscannedTagTable = () => { - const { unscannedTags, unscannedTagCount, scannedTagCount } = this.props; - const { showUnscannedTags } = this.state; - if (!unscannedTagCount) { - return null; - } - //Nautilus scan results exist --> show the button instead of the table - if (showUnscannedTags === 'unknown' && scannedTagCount) { - return ( -
    - -
    - ); - } - //Nautilus scan results exist and the button has been pressed to show unscanned tags - if (showUnscannedTags === 'show' && scannedTagCount) { - return ( - - - -
    - Unscanned Tags -
    -
    -
    - -
    Tag Name
    -
    Compressed Size
    -
    Last Updated
    - -
    - {unscannedTags.map(this.mkUnscannedTagRow)} -
    - ); - - } - return ( - - -
    Tag Name
    -
    Compressed Size
    -
    Last Updated
    - -
    - {unscannedTags.map(this.mkUnscannedTagRow)} -
    - ); - } - - mkScannedTagRow = (tag) => { - const { status } = this.props; - const tagName = tag.name; - const tagStatus = status.getIn(['deleteRepoTag', tagName], new StatusRecord()); - return ( - - ); - } - - mkScannedTagTable = () => { - const { scannedTags, scannedTagCount } = this.props; - if (!scannedTagCount) { - return null; - } - const tooltipTitle = `Scanned Images`; - const tooltipText = `Docker supports and maintains a set of tags that are recommended for use based on the most secure and quality images. To view the rest of the tag instances for this repository, view "Unscanned Images".`; - const tooltipContent = ( -
    -
    {tooltipTitle}
    -
    {tooltipText}
    -
    - ); - const questionMark = ( - -
    - -
    -
    - ); - //sort scannedTags by `created_at` date, from most recent to oldest - scannedTags.sort((tag1, tag2) => { - if (moment(tag1.created_at).isSame(tag2.created_at)) { - return moment(tag1.last_updated).isAfter(tag2.last_updated) ? -1 : 1; - } - return moment(tag1.created_at).isAfter(tag2.created_at) ? -1 : 1; - }); - return ( - - - -
    - Scanned Images   - {questionMark} -
    -
    -
    - {scannedTags.map(this.mkScannedTagRow)} -
    - ); - } - - render() { - const { scannedTagCount, unscannedTagCount } = this.props; - - if (!scannedTagCount && !unscannedTagCount) { - return ( - - -
    No tags for this repository.
    -
    -
    - ); - } - - return ( -
    - { this.mkScannedTagTable() } - { this.mkUnscannedTagTable() } -
    - ); - } -} - -export default TagDisplay; diff --git a/app/scripts/components/repo/repo_details/info/Comment.css b/app/scripts/components/repo/repo_details/info/Comment.css deleted file mode 100644 index a35551d669..0000000000 --- a/app/scripts/components/repo/repo_details/info/Comment.css +++ /dev/null @@ -1,45 +0,0 @@ -@import "dux/css/colors.css"; -@import "dux/css/box.css"; - -.closeButton { - color: white; - display: inline-block; - background: var(--oil); - border-radius: 100%; - width: 1.5rem; - height: 1.5rem; - text-align: center; - margin-right: .5rem; -} -.commentHead { - display: flex; - margin-bottom: .75rem; -} -.commentDelete { - cursor: pointer; - &:hover { - color: var(--primary-5); - } -} -.avatar { - width: 50px; - height: 50px; - border-radius: var(--global-radius); -} - -.content { - -} - -.name { - color: darken(gray, 30%); - font-weight: 500; -} -.time { - font-size: 0.8rem; - color: lighten(gray, 15%); -} - -.commentInfo { - margin: .5rem 1rem; -} \ No newline at end of file diff --git a/app/scripts/components/repo/repo_details/info/Comment.jsx b/app/scripts/components/repo/repo_details/info/Comment.jsx deleted file mode 100644 index 7ff41577fa..0000000000 --- a/app/scripts/components/repo/repo_details/info/Comment.jsx +++ /dev/null @@ -1,76 +0,0 @@ -'use strict'; - -import styles from './Comment.css'; -import React, { PropTypes, createClass } from 'react'; -import { Link } from 'react-router'; -import moment from 'moment'; -import Card, { Block } from '@dux/element-card'; -import Markdown from '@dux/element-markdown'; -import FA from '../../../common/FontAwesome.jsx'; -import { mkAvatarForNamespace } from 'utils/avatar'; - -var debug = require('debug')('RepositoryComment'); - -var CommentType = PropTypes.shape({ - updated_on: PropTypes.string.isRequired, - created_on: PropTypes.string.isRequired, - comment: PropTypes.string.isRequired, - user: PropTypes.string.isRequired, - id: PropTypes.number.isRequired -}); - -var UserType = PropTypes.shape({ - username: PropTypes.string.isRequired -}); - -var DeleteButton = createClass({ - propTypes: { - deleteRepoComment: PropTypes.func.isRequired - }, - render() { - return ( -
    - -
    - ); - } -}); - -export default createClass({ - displayName: 'RepositoryComment', - propTypes: { - comment: CommentType, - deleteRepoComment: PropTypes.func.isRequired, - user: UserType - }, - render() { - var comment = this.props.comment; - var maybeDeleteButton = null; - - if(this.props.user.username === this.props.comment.user) { - maybeDeleteButton = ; - } - const avatar = mkAvatarForNamespace(this.props.comment.user); - - return ( - - -
    -
    - -
    -
    -
    {comment.user}
    -
    {moment(comment.created_on).fromNow()}
    -
    - {maybeDeleteButton} -
    -
    -
    - {comment.comment} -
    -
    -
    - ); - } -}); diff --git a/app/scripts/components/repo/repo_details/info/Comments.css b/app/scripts/components/repo/repo_details/info/Comments.css deleted file mode 100644 index c7287ec432..0000000000 --- a/app/scripts/components/repo/repo_details/info/Comments.css +++ /dev/null @@ -1,23 +0,0 @@ -.header { - font-weight: 500; - font-size: 1.25rem; -} -.addCommentBox { -} -.addCommentBoxTextArea { - color: black; - background: white; - width: 100%; - height: 100px; - resize: none; - &:focus { - background: white; - } -} - -.button { - margin-top: .5rem; -} -.closed { - display: none; -} \ No newline at end of file diff --git a/app/scripts/components/repo/repo_details/info/Comments.jsx b/app/scripts/components/repo/repo_details/info/Comments.jsx deleted file mode 100644 index 2fadb3cbe8..0000000000 --- a/app/scripts/components/repo/repo_details/info/Comments.jsx +++ /dev/null @@ -1,221 +0,0 @@ -'use strict'; - -import React, { - PropTypes, - createClass -} from 'react'; -import { findDOMNode } from 'react-dom'; -import _ from 'lodash'; -import connectToStores from 'fluxible-addons-react/connectToStores'; - -import RepositoryCommentsStore from '../../../../stores/RepositoryCommentsStore'; -import Comment from './Comment'; -import classnames from 'classnames'; -import addRepoComment from '../../../../actions/addRepoComment.js'; -import getRepoComments from '../../../../actions/getRepoComments.js'; -import deleteRepoComment from '../../../../actions/deleteRepoComment.js'; -import Pagination from '../../../common/Pagination.jsx'; -import { Button } from 'dux'; - -import styles from './Comments.css'; - -var debug = require('debug')('Comments'); - -let mkCommentElement = function(comment) { - return ( - - ); -}; - -var AddCommentButton = createClass({ - displayName: 'AddComment', - contextTypes: { - executeAction: PropTypes.func.isRequired - }, - propTypes: { - JWT: PropTypes.string.isRequired, - commentAdded: PropTypes.func.isRequired - }, - getInitialState: function() { - return { - commentBoxStatus: 'closed', - commentBoxValue: '' - }; - }, - _toggleComment(e){ - e.preventDefault(); - if (this.state.commentBoxStatus === 'open') { - this.setState({ - commentBoxStatus: 'closed', - commentBoxValue: '' - }); - } else { - this.setState({ - commentBoxStatus: 'open' - }, () => { - let node = findDOMNode(this.refs.commentTextArea); - node.focus(); - node.scrollTop = node.scrollHeight; - }); - } - }, - _commentChange(e) { - e.preventDefault(); - this.setState({ - commentBoxValue: e.target.value - }); - }, - _leaveComment(e) { - e.preventDefault(); - var comment = this.state.commentBoxValue; - var repoShortName = this.props.namespace + '/' + this.props.name; - this.setState({ - commentBoxValue: '' - }); - this.context.executeAction(addRepoComment, {jwt: this.props.JWT, repoShortName: repoShortName, comment: comment}); - this.props.commentAdded(); - }, - render() { - const addCommentClass = classnames({ - 'row': true, - [styles.addCommentBox]: true, - [styles[this.state.commentBoxStatus]]: true - }); - - let commentButton = 'Add Comment'; - let buttonSize = 'small'; - let commentButtonIntent = 'primary'; - if (this.state.commentBoxStatus === 'open') { - commentButton = 'Cancel'; - buttonSize = 'tiny'; - commentButtonIntent = 'alert'; - } - return ( -
    -
    -
    - -
    -
    -
    -
    - Add a Comment (accepts markdown) -
    - - ); - const submit = this.updateLongDescription; - return ( - - - -
    - {input} - {maybeError} -
    -
      -
    • - -
    • -
    • - -
    • -
    -
    -
    - -
    -
    - ); - } - - render() { - const { - canEdit, - isEditing, - successfulSave, - fields - } = this.props; - const { longDescription } = this.props.values; - let cardHeading = `Full Description`; - - if (isEditing) { - cardHeading = `Full Description (Optional, Limit 25,000 Characters)`; - return this.renderForm(cardHeading); - } else { - const headingActions = canEdit ? [{ - key: 'edit', - icon: 'fa-edit', - action: this.toggleEditMode - }] : []; - let formattedDescription; - if (!longDescription) { - formattedDescription = ( -
    -

    - Full description is empty for this repo. -

    -
    ); - } else { - formattedDescription = ({longDescription}); - } - const maybeSuccessClass = classnames({ - [styles.successfulSave]: successfulSave - }); - - let maybeSuccess = ; - if (successfulSave) { - maybeSuccess = ( -
    - {fields.longDescription.success} -
    - ); - } - return ( - - -
    - {maybeSuccess} - {formattedDescription} -
    -
    -
    - ); - } - } -} - -export default connectToStores(RepoFullDescription, - [RepoDetailsLongDescriptionFormStore], - function({ getStore }, props) { - return getStore(RepoDetailsLongDescriptionFormStore).getState(); - }); diff --git a/app/scripts/components/repo/repo_details/info/RepoShortDescription.css b/app/scripts/components/repo/repo_details/info/RepoShortDescription.css deleted file mode 100644 index 4f653e3006..0000000000 --- a/app/scripts/components/repo/repo_details/info/RepoShortDescription.css +++ /dev/null @@ -1,32 +0,0 @@ -@import "dux/css/colors.css"; -@import "dux/css/box.css"; - -input.textArea { - background-color: var(--white); - &:focus { - border: 1px solid var(--primary-1); - background-color: var(--white); - } -} -.text { - margin-bottom: var(--default-margin); -} -input.error { - border: 1px solid var(--primary-5); - &:focus { - border: 1px solid var(--primary-5); - } -} -.errorText { - composes: text; - color: var(--primary-5); -} - -.successText { - composes: text; - color: var(--primary-2); -} - -.successfulSave { - border: 1px solid var(--primary-2); -} \ No newline at end of file diff --git a/app/scripts/components/repo/repo_details/info/RepoShortDescription.jsx b/app/scripts/components/repo/repo_details/info/RepoShortDescription.jsx deleted file mode 100644 index a300c5d028..0000000000 --- a/app/scripts/components/repo/repo_details/info/RepoShortDescription.jsx +++ /dev/null @@ -1,179 +0,0 @@ -'use strict'; - -import React, { PropTypes, Component } from 'react'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import attemptChangeShortDescription from 'actions/attemptChangeShortDescription'; -import RepoDetailsShortDescriptionFormStore from 'stores/RepoDetailsShortDescriptionFormStore'; -import shortDescriptionUpdateFormField from 'actions/shortDescriptionUpdateFormField'; -import toggleShortDescriptionEdit from 'actions/toggleShortDescriptionEdit'; -import Card, { Block } from '@dux/element-card'; -import { Button } from 'dux'; -import classnames from 'classnames'; -import styles from './RepoShortDescription.css'; -import SimpleInput from 'common/SimpleInput'; -const { string, object, bool, number, func, shape } = PropTypes; -const debug = require('debug')('RepoShortDescription'); - - -class RepoShortDescription extends Component { - static propTypes = { - canEdit: bool.isRequired, - name: string.isRequired, - namespace: string.isRequired, - JWT: string, - isEditing: bool.isRequired, - successfulSave: bool, - values: shape({ - shortDescription: string - }) - } - - static contextTypes = { - executeAction: func.isRequired - } - - static defaultProps = { - successfulSave: false, - isEditing: false - } - - toggleEditMode = (e) => { - this.context.executeAction(toggleShortDescriptionEdit, { isEditing: !this.props.isEditing }); - } - - onChange = (fieldKey) => { - return (e) => { - this.context.executeAction(shortDescriptionUpdateFormField, { - fieldKey, - fieldValue: e.target.value - }); - }; - } - - updateShortDescription = (event) => { - event.preventDefault(); - const { JWT, - name, - namespace - } = this.props; - const { shortDescription } = this.props.values; - this.context.executeAction(attemptChangeShortDescription, - { - jwt: JWT, - repoShortName: namespace + '/' + name, - shortDescription: shortDescription - }); - } - renderForm = (cardHeading) => { - let maybeError = ; - const shortDesc = this.props.fields.shortDescription; - const currentShortDesc = this.props.values.shortDescription; - const maxChars = 100; - let hasError = false; - if (shortDesc.hasError) { - /* check for error from request (post submit). success is handled by non-edit card */ - maybeError = (
    {shortDesc.error}
    ); - hasError = true; - } else if (currentShortDesc.length > maxChars) { - /* check for typed input that's too long - not caught until submit otherwise */ - const tooMany = currentShortDesc.length - maxChars; - - const msg = `Maximum ${maxChars} characters. You are over the limit by: ${tooMany}`; - maybeError = (
    {msg}
    ); - hasError = true; - } - const intent = hasError ? 'alert' : 'primary'; - const textAreaClass = classnames({ - [styles.textArea]: true, - [styles.error]: hasError - }); - const input = ( - - ); - const submit = this.updateShortDescription; - return ( - - -
    -
    - {input} - {maybeError} -
    -
      -
    • - -
    • -
    • - -
    • -
    -
    -
    -
    -
    -
    - ); - } - - render() { - const { - canEdit, - isEditing, - successfulSave, - fields - } = this.props; - const { shortDescription } = this.props.values; - let cardHeading = `Short Description`; - - if (isEditing) { - cardHeading = `Short Description (Optional, Limit 100 Characters)`; - return this.renderForm(cardHeading); - } else { - let headingActions = canEdit ? [{ - key: 'edit', - icon: 'fa-edit', - action: this.toggleEditMode - }] : []; - let maybeSuccessClass = classnames({ - [styles.successfulSave]: successfulSave - }); - let maybeSuccess = ; - if (successfulSave) { - maybeSuccess = (
    - {fields.shortDescription.success} -
    ); - } - return ( - - -
    - {maybeSuccess} - {shortDescription || 'Short description is empty for this repo.'} -
    -
    -
    - ); - } - } -} - -export default connectToStores(RepoShortDescription, - [RepoDetailsShortDescriptionFormStore], - function({ getStore }, props) { - return getStore(RepoDetailsShortDescriptionFormStore).getState(); - }); diff --git a/app/scripts/components/repo/repo_details/nautilusUtils.js b/app/scripts/components/repo/repo_details/nautilusUtils.js deleted file mode 100644 index f6a911cda1..0000000000 --- a/app/scripts/components/repo/repo_details/nautilusUtils.js +++ /dev/null @@ -1,63 +0,0 @@ -'use strict'; - -const keyMirror = require('keymirror'); -import forEach from 'lodash/collection/forEach'; -import trim from 'lodash/string/trim'; - -export const mkComponentId = (component) => { - const { component: name, version } = component; - const id = version ? `${name}:${version}` : `${name}:`; - return trim(id); -}; - -export const mapCvss = (cvss) => { - if (cvss <= 0) { - return 'secure'; - } - if (cvss < 4) { - return 'minor'; - } - if (cvss < 7) { - return 'major'; - } - return 'critical'; -}; - -// Get a map of component key to its highest CVSS score -// { bgaes: 4.5, } -export const getHighestComponentCvss = (components, vulnerabilities) => { - let highestComponentCvss = {}; - forEach(components, (c, compName) => { - let cvssMax = 0; - forEach(c.vulnerabilities, v => { - let { cvss } = vulnerabilities[v]; - if (cvss > cvssMax) { - cvssMax = cvss; - } - }); - highestComponentCvss[compName] = cvssMax; - }); - return highestComponentCvss; -}; - -// Given a list of severities returns the highest severity string using mapCvss -// Usage: -// getHighestSeverity([0.5, 2, 4]) -// getHighestSeverity(...cvssList) -export const getHighestSeverity = (...cvss) => { - if (cvss.length === 0) { - return -1; - } - let maxScore = 0; - for (let i in cvss) { - if (cvss[i] > maxScore) { - maxScore = cvss[i]; - } - } - return mapCvss(maxScore); -}; - -export const consts = keyMirror({ - FAILED: null, - IN_PROGRESS: null -}); diff --git a/app/scripts/components/repo/repo_details/scannedTag/ComponentGrid.css b/app/scripts/components/repo/repo_details/scannedTag/ComponentGrid.css deleted file mode 100644 index 14c5447c8b..0000000000 --- a/app/scripts/components/repo/repo_details/scannedTag/ComponentGrid.css +++ /dev/null @@ -1,5 +0,0 @@ -.componentGrid { - display: flex; - flex-flow: row wrap; - align-content: flex-start; -} diff --git a/app/scripts/components/repo/repo_details/scannedTag/ComponentGrid.jsx b/app/scripts/components/repo/repo_details/scannedTag/ComponentGrid.jsx deleted file mode 100644 index 0112e09fe7..0000000000 --- a/app/scripts/components/repo/repo_details/scannedTag/ComponentGrid.jsx +++ /dev/null @@ -1,70 +0,0 @@ -'use strict'; - -import React, { Component, PropTypes } from 'react'; -const { object, array, func, string } = PropTypes; -import { mapCvss, getHighestSeverity } from '../nautilusUtils.js'; -import styles from './ComponentGrid.css'; -import Square from './Square'; -import forEach from 'lodash/collection/forEach'; -import { mkComponentId } from '../nautilusUtils'; - -export default class ComponentGrid extends Component { - static propTypes = { - componentsSortedBySeverity: array.isRequired, - onClick: func, - selectedComponent: string, - vulnerabilities: object - } - - static defaultProps = { - selectedComponent: '' - } - - getNumVulnsBySeverity = (component) => { - const { vulnerabilities: vulns } = this.props; - let numVulns = { - critical: 0, - major: 0, - minor: 0, - secure: 0 - }; - forEach(component.vulnerabilities, (v) => { - numVulns[mapCvss(vulns[v].cvss)]++; - }); - return numVulns; - } - - mkComponentSquare = (component) => { - const { selectedComponent, onClick, vulnerabilities: vulns } = this.props; - const componentFullName = mkComponentId(component); - const isSelected = selectedComponent === componentFullName; - const numVulnsBySeverity = this.getNumVulnsBySeverity(component); - let severity = 'secure'; - if (numVulnsBySeverity.critical) { - severity = 'critical'; - } else if (numVulnsBySeverity.major) { - severity = 'major'; - } else if (numVulnsBySeverity.minor) { - severity = 'minor'; - } - - return ( - - ); - } - - render() { - const { componentsSortedBySeverity } = this.props; - return ( -
    - { componentsSortedBySeverity.map(this.mkComponentSquare) } -
    - ); - } -} diff --git a/app/scripts/components/repo/repo_details/scannedTag/Layer.css b/app/scripts/components/repo/repo_details/scannedTag/Layer.css deleted file mode 100644 index 69374b57f3..0000000000 --- a/app/scripts/components/repo/repo_details/scannedTag/Layer.css +++ /dev/null @@ -1,82 +0,0 @@ -@import 'dux/css/box.css'; -@import 'dux/css/colors.css'; -/* Note: tooltip CSS is globally styled in styles/vender-overrides/rc-tooltip.css */ - -.grey { - color: #CECED9; -} - -.row { - padding: 1rem 0 1rem 1.5rem; - position: relative; -} - -.unselectedRow { - composes: row; - border-top: 1px solid #E4E4E4; -} - -.selectedRow { - composes: row; - border: 1px solid #E4E4E4; - border-radius: var(--global-radius); -} - -/* remove top border for unselected row following a selected row */ -.selectedRow + .unselectedRow { - border-top: none; -} - -.check { - color: #6BCEC0; -} - -.chevron { - color: #CECED9; - cursor: pointer; - display: inline-block; - float: right; - margin: 6px 0; -} - -.layerSize { - composes: grey; - display: inline-block; - font-size: 0.8rem; -} - -.dockerCommandLine { - text-overflow: ellipsis; - overflow: hidden; - width:100%; - display: inline; - margin-right: 0.5rem; - font-size: 1.1rem; - color: #78828F; -} -a .dockerCommandLine { - color: #22b8eb; -} - -.title { - margin-bottom: 0.5rem; -} - -.layerNum { - position: absolute; - left: -5px; - color: #bbb; - top: 2px; - font-weight: 500; -} - -.baseLayerLabel { - background-color: #E7E7E7; - color: var(--jumbo); - border-radius: var(--global-radius); - padding: 0.2rem 0.5rem; -} - -.numVulnerableComps { - margin-right: 0.5rem; -} diff --git a/app/scripts/components/repo/repo_details/scannedTag/Layer.jsx b/app/scripts/components/repo/repo_details/scannedTag/Layer.jsx deleted file mode 100644 index 0ed47f870b..0000000000 --- a/app/scripts/components/repo/repo_details/scannedTag/Layer.jsx +++ /dev/null @@ -1,234 +0,0 @@ -'use strict'; - -import React, { Component, PropTypes } from 'react'; -import ComponentGrid from './ComponentGrid'; -import LayerVulnerabilitiesTable from './LayerVulnerabilitiesTable'; -import size from 'lodash/collection/size'; -import map from 'lodash/collection/map'; -const { object, shape, string, bool, func, number } = PropTypes; -import styles from './Layer.css'; -import FontAwesome from 'common/FontAwesome'; -import ui from 'redux-ui'; -import numeral from 'numeral'; -import forEach from 'lodash/collection/forEach'; -import { getHighestComponentCvss, mapCvss } from '../nautilusUtils.js'; -import Tooltip from 'rc-tooltip'; -import classnames from 'classnames'; -import { VelocityComponent } from 'velocity-react'; -const debug = require('debug')('hub:Layer'); - -// Layer is a row in the table of layers for a ScannedTag -@ui({ - state: { - selectedComponent: '', - isExpanded: false, - // if a component is selected and unselected, should the table still show? - shouldReturnToExpanded: false - } -}) -export default class Layer extends Component { - //vulnerabilities and components are just for this layer - static propTypes = { - ui: shape({ - selectedComponent: string, - isExpanded: bool, - shouldReturnToExpanded: bool - }), - updateUI: func, - - layerNum: number, - components: object.isRequired, - layer: object.isRequired, - vulnerabilities: object.isRequired - } - - truncateStringInMiddle = (str, max = 25, sep = `...`) => { - //don't truncate if it's less than max chars - const sepLen = sep.length; - const len = str.length; - if (len < max || sepLen > max) { return str; } - const n = -0.5 * (max - len - sepLen); - const center = len / 2; - return str.substr(0, center - n) + sep + str.substr(len - center + n); - } - - mkTitleRow = () => { - const { components, layer, vulnerabilities, ui: { isExpanded } } = this.props; - const truncateAtChars = 45; - let titleText = layer.docker_command_line; - if (titleText.length > truncateAtChars) { - titleText = this.truncateStringInMiddle(layer.docker_command_line, truncateAtChars); - } - //add link to clickable rows - let title =
    { titleText }
    ; - if (size(layer.components)) { - title = ( - -
    - { titleText } -
    -
    - ); - } - //add tooltip - const instruction = ( - { layer.docker_command_line }
    } - placement='top' - mouseEnterDelay={ 0.1 } - mouseLeaveDelay={ 0.3 } - align={ { overflow: { adjustY: 0 } } }> - { title } - - ); - const layerSize =
    Compressed size: { numeral(layer.size).format('0.0b') }
    ; - let chevron; - if (size(components)) { - chevron = ( -
    - - - -
    - ); - } - return
    { instruction }{ layerSize } { chevron }
    ; - } - - mkLine = (numVulnerableComps, numComps, layerType) => { - let vulnComps, baseLayer; - if (!numComps) { - vulnComps = ( - - No components in this layer - - ); - } else if (!numVulnerableComps && numComps) { - vulnComps = ( - - -  No vulnerable components - - ); - } else if (numVulnerableComps === 1) { - vulnComps = 1 vulnerable component; - } else if (numComps) { - //nothing for layers with no components - vulnComps = {numVulnerableComps} vulnerable components; - } - - // add base layer tag if relevant - if (layerType === 'BASE') { - baseLayer = Base Layer; - } - return
    {vulnComps} {baseLayer}
    ; - } - - toggleExpanded = () => { - const { updateUI } = this.props; - const { selectedComponent, isExpanded, shouldReturnToExpanded } = this.props.ui; - if (!!selectedComponent && isExpanded) { - //clear selected component when closing - updateUI('selectedComponent', ''); - } - updateUI('shouldReturnToExpanded', !shouldReturnToExpanded); - updateUI('isExpanded', !isExpanded); - } - - selectComponent = (componentId) => { - const { updateUI } = this.props; - const { isExpanded, shouldReturnToExpanded } = this.props.ui; - if (!isExpanded && !!componentId) { - updateUI('isExpanded', true); - } - //close the layer if it was closed before you selected then unselected a component - if (isExpanded && !componentId && !shouldReturnToExpanded) { - updateUI('isExpanded', false); - } - updateUI('selectedComponent', componentId); - } - - viewAll = () => { - const { updateUI } = this.props; - const { selectedComponent } = this.props.ui; - //can only be triggered when isExpanded && selectedComponent !== '' - updateUI('selectedComponent', ''); - } - - sortComponentsBySeverity = (highestComponentCvss) => { - //layer may not have any components - const { components } = this.props; - if (!size(components)) { - return []; - } - return map(components, (c, key) => { - return { ...c, key }; - }).sort( (c1, c2) => { - return highestComponentCvss[c2.key] - highestComponentCvss[c1.key]; - }); - } - - getNumVulnerableComponents = (highestComponentCvss) => { - const { components } = this.props; - let numVulnComps = 0; - forEach(components, (c, key) => { - //get the component's highest cvss and the severity of it - if (mapCvss(highestComponentCvss[key]) !== 'secure') { - numVulnComps++; - } - }); - return numVulnComps; - } - - render() { - const { selectedComponent, isExpanded } = this.props.ui; - const { components, layer, vulnerabilities } = this.props; - // map of { componentName: highestCvss } - const highestComponentCvss = getHighestComponentCvss(components, vulnerabilities); - const componentsSortedBySeverity = this.sortComponentsBySeverity(highestComponentCvss); - //nothing displayed for non-base layers with no components - let maybeLine, maybeTable; - const numComps = size(components); - if (numComps && isExpanded) { - maybeTable = ( - - ); - } - if (!isExpanded) { - const numVulnerableComponents = this.getNumVulnerableComponents(highestComponentCvss); - maybeLine = this.mkLine(numVulnerableComponents, numComps, layer.type); - } - let maybeGrid; - //text is displayed instead of table when there are no components (#NOP) - if (numComps) { - maybeGrid = ( - - ); - } - const rowClasses = classnames({ - 'row': true, - [styles.unselectedRow]: !isExpanded, - [styles.selectedRow]: isExpanded - }); - return ( -
    -
    - { (this.props.layerNum + 1) } - { this.mkTitleRow() } - { maybeLine } - { maybeTable } -
    -
    - { maybeGrid } -
    -
    - ); - } -} diff --git a/app/scripts/components/repo/repo_details/scannedTag/LayerVulnerabilitiesTable.css b/app/scripts/components/repo/repo_details/scannedTag/LayerVulnerabilitiesTable.css deleted file mode 100644 index fc36086c1e..0000000000 --- a/app/scripts/components/repo/repo_details/scannedTag/LayerVulnerabilitiesTable.css +++ /dev/null @@ -1,61 +0,0 @@ -.grey { - color: #B1B5B9; -} - -hr.border { - color: #E4E4E4; - margin: 0.5rem 0 0.5rem; -} - -.headerText { - composes: grey; - text-transform: uppercase; - margin: 0.5rem 0 0.25rem; - font-weight: 500; - font-size: 0.85rem; -} - -.critical { - color: #EB3E46; -} - -.major { - color: #FF8546; -} - -.minor { - color: #FFC458; -} - -.secure { - color: #D3DFDD; -} - -.licenseType { - composes: grey; - font-size: 0.8rem; -} - -.severity { - text-align: right; -} - -.vulnerabilityLines { - margin-bottom: 0.25rem; -} - -.viewAll { - composes: grey; - border-top: 1px solid #C4CDDA; - border-bottom: 1px solid #C4CDDA; - text-align: center; - padding: 0.5rem 0; - cursor: pointer; - text-transform: uppercase; - font-size: 0.85rem; - margin-top: 0.5rem; -} - -.wrapWords { - word-wrap: break-word; -} diff --git a/app/scripts/components/repo/repo_details/scannedTag/LayerVulnerabilitiesTable.jsx b/app/scripts/components/repo/repo_details/scannedTag/LayerVulnerabilitiesTable.jsx deleted file mode 100644 index 5b860ece99..0000000000 --- a/app/scripts/components/repo/repo_details/scannedTag/LayerVulnerabilitiesTable.jsx +++ /dev/null @@ -1,162 +0,0 @@ -'use strict'; - -import React, { Component, PropTypes } from 'react'; -const { object, bool, array, func, string } = PropTypes; -import styles from './LayerVulnerabilitiesTable.css'; -import { mapCvss, mkComponentId } from '../nautilusUtils.js'; -import forEach from 'lodash/collection/forEach'; -import capitalize from 'lodash/string/capitalize'; -import FontAwesome from 'common/FontAwesome'; -import classnames from 'classnames'; -import Tooltip from 'rc-tooltip'; - -export default class LayerVulnerabilitiesTable extends Component { - static propTypes = { - componentsSortedBySeverity: array.isRequired, - selectedComponent: string, - isExpanded: bool, - viewAll: func, - vulnerabilities: object.isRequired - } - - static defaultProps = { - selectedComponent: '' - } - - mkHeader = () => { - return ( -
    - -
    Component
    -
    Vulnerability
    -
    Severity
    -
    -
    - ); - } - - mkComponentArea = (fullName, license, license_type) => { - return ( -
    -
    { fullName }
    -
    - { `${license}:${capitalize(license_type)} License` } -
    -
    - ); - } - - mkVulnerabilityArea = (fullName, vulns) => { - if (!vulns.length) { - return
    No known vulnerabilities
    ; - } - return vulns.map( v => { - const tooltipContent = ( -
    -
    { v.cve }
    -
    { v.summary }
    -
    - ); - return ( - - - - ); - }); - } - - mkSeverityArea = (fullName, vulns) => { - if (!vulns.length) { - let classes = classnames({ - [styles.secure]: true, - [styles.vulnerabilityLines]: true, - [styles.severity]: true - }); - return
    N/A
    ; - } - return vulns.map( v => { - let classes = classnames({ - [styles[v.severity]]: true, - [styles.vulnerabilityLines]: true, - [styles.severity]: true - }); - return ( -
    - { capitalize(v.severity) } -
    - ); - }); - } - - mkComponentRow = (component) => { - const { - license, - license_type, - component: name, - version, - vulnerabilities - } = component; - const { selectedComponent, vulnerabilities: layerVulnerabilities } = this.props; - const id = mkComponentId(component); - // only render this row if there is NOT a selected component OR this is the selected component - let content; - if (!selectedComponent || selectedComponent === id) { - const fullName = version ? `${name} ${version}` : name; - const componentArea = this.mkComponentArea(fullName, license, license_type); - let componentVulns = []; - forEach(vulnerabilities, (v) => { - const vuln = layerVulnerabilities[v]; - //add severity key to vuln object: ex. severity: 'minor' - componentVulns.push({ ...vuln, severity: mapCvss(vuln.cvss)}); - }); - //sort component vulnerabilities by cvss so most vulnerable is first - componentVulns.sort((v1, v2) => v2.cvss - v1.cvss); - const vulnerabilityArea = this.mkVulnerabilityArea(fullName, componentVulns); - const severityArea = this.mkSeverityArea(fullName, componentVulns); - content = ( -
    -

    -
    {componentArea}
    -
    {vulnerabilityArea}
    -
    {severityArea}
    -
    - ); - } - return content; - } - - render() { - const { - componentsSortedBySeverity, - selectedComponent, - isExpanded, - viewAll - } = this.props; - let viewAllSection; - if (selectedComponent) { - viewAllSection = ( -
    - { `View All `} -
    - ); - } - return ( -
    - { this.mkHeader() } - { componentsSortedBySeverity.map(this.mkComponentRow) } - { viewAllSection } -
    - ); - } -} diff --git a/app/scripts/components/repo/repo_details/scannedTag/ScanHeader.css b/app/scripts/components/repo/repo_details/scannedTag/ScanHeader.css deleted file mode 100644 index 6ecdfbf0e3..0000000000 --- a/app/scripts/components/repo/repo_details/scannedTag/ScanHeader.css +++ /dev/null @@ -1,50 +0,0 @@ -@import 'dux/css/colors.css'; - -/* Top section with vulnerability counts */ -.verticalSpacing { - line-height: 1.2rem; -} - -.headerRow { - padding-bottom: 1rem; -} - -.vulnerabilityText { - composes: verticalSpacing; - font-size: 1.2rem; - padding-bottom: 0.5rem; -} - -.feedback { - composes: verticalSpacing; - text-align: right; -} - -.feedbackLink { - color: var(--secondary-5); -} - -/* same color as layer titles */ -.lastScanned { - color: #78828f; -} - -.inlineBlock { - display: inline-block; -} - -.bigCheck { - composes: inlineBlock; - color: #6bcec0; - padding-right: 1rem; -} - -/* Layers and Components section */ -.tableHeader { - border-top: 1px solid #E4E4E4; - padding: 0.5rem 0; -} - -.componentsTitle { - padding-left: 1rem; -} diff --git a/app/scripts/components/repo/repo_details/scannedTag/ScanHeader.jsx b/app/scripts/components/repo/repo_details/scannedTag/ScanHeader.jsx deleted file mode 100644 index 5b33a5ff5f..0000000000 --- a/app/scripts/components/repo/repo_details/scannedTag/ScanHeader.jsx +++ /dev/null @@ -1,64 +0,0 @@ -'use strict'; - -import React from 'react'; -import styles from './ScanHeader.css'; -import capitalize from 'lodash/string/capitalize'; -import size from 'lodash/collection/size'; -import FontAwesome from 'common/FontAwesome'; -import moment from 'moment'; -import { consts } from '../nautilusUtils'; - -const ScanHeader = ({ scan, componentsBySeverity }) => { - const { critical, major, minor, secure } = componentsBySeverity; - const { reponame, tag, sha256sum, completed_at, latest_scan_status } = scan; - const numTotalComponents = critical.length + major.length + minor.length + secure.length; - const numVulnerableComponents = numTotalComponents - secure.length; - const components = numTotalComponents === 1 ? `component` : `components`; - const isOrAre = numVulnerableComponents === 1 ? `is` : `are`; - const lastScanned = latest_scan_status === consts.IN_PROGRESS ? `New scan in progress, showing results from ${moment(completed_at).fromNow()}` : `Scanned ${moment(completed_at).fromNow()}`; - let vulnText, vulnArea; - if (!numVulnerableComponents) { - vulnText =
    Your image is clean! No known vulnerabilities were found.
    ; - vulnArea = ( -
    -
    - -
    -
    -
    {vulnText}
    -
    {lastScanned}
    -
    -
    - ); - } else { - vulnText = `${numVulnerableComponents} of ${numTotalComponents} ${components} ${isOrAre} vulnerable`; - vulnArea = ( -
    -
    {vulnText}
    -
    {lastScanned}
    -
    - ); - } - const feedback = ( - - Provide Feedback - - ); - return ( -
    -
    -
    - {vulnArea} -
    -
    {feedback}
    -
    -
    -
    Layers
    -
    Components
    -
    -
    - ); -}; - -export default ScanHeader; diff --git a/app/scripts/components/repo/repo_details/scannedTag/Square.css b/app/scripts/components/repo/repo_details/scannedTag/Square.css deleted file mode 100644 index fccd037205..0000000000 --- a/app/scripts/components/repo/repo_details/scannedTag/Square.css +++ /dev/null @@ -1,59 +0,0 @@ -.square { - margin-right: 1px; - margin-bottom: 1px; - width: 50px; - height: 50px; - cursor: pointer; - user-select: none; -} - -.square:hover { - border: 1px solid black; -} - -.solid { - opacity: 1; -} - -.faded { - opacity: 0.4; -} - -.outline { - border: 1px solid black; -} - -.component { - color: #B1B5B9; - text-transform: uppercase; - font-weight: 500; - font-size: 0.85rem; -} - -.tooltipSquare { - display: inline-block; - width: 11px; - height: 11px; - vertical-align: middle; - margin-right: .25rem; -} - -.vulnLineWrapper { - padding-top: 0.25rem; -} - -.critical { - background-color: #EB3E46; -} - -.major { - background-color: #FF8546; -} - -.minor { - background-color: #FFC458; -} - -.secure { - background-color: #D3DFDD; -} diff --git a/app/scripts/components/repo/repo_details/scannedTag/Square.jsx b/app/scripts/components/repo/repo_details/scannedTag/Square.jsx deleted file mode 100644 index abc557fd80..0000000000 --- a/app/scripts/components/repo/repo_details/scannedTag/Square.jsx +++ /dev/null @@ -1,110 +0,0 @@ -'use strict'; - -import React, { Component, PropTypes } from 'react'; -const { object, bool, func, shape, oneOf, number } = PropTypes; -import classnames from 'classnames'; -import styles from './Square.css'; -import capitalize from 'lodash/string/capitalize'; -import Tooltip from 'rc-tooltip'; -import { mkComponentId } from '../nautilusUtils.js'; -const severities = ['critical', 'major', 'minor', 'secure']; - -export default class Square extends Component { - static propTypes = { - component: object.isRequired, - isSelected: bool, - isLayerSelected: bool, - numVulnsBySeverity: shape({ - critical: number, - major: number, - minor: number - }), - onClick: func.isRequired, - severity: oneOf(severities) - } - - static defaultProps = { - isSelected: false, - isLayerSelected: false, - severity: 'secure' - } - - onClick = (e) => { - const { isSelected, component } = this.props; - if (isSelected) { - //unselect component - this.props.onClick(''); - } else { - // Note: this is the ID that normalizr uses to refer to components - this.props.onClick(mkComponentId(component)); - } - } - - mkTooltipContent = () => { - const { component, version } = this.props.component; - const { critical, major, minor } = this.props.numVulnsBySeverity; - let vulnList = ( -
    -
    { this.mkTooltipVulnLine('critical', critical) }
    -
    { this.mkTooltipVulnLine('major', major) }
    -
    { this.mkTooltipVulnLine('minor', minor) }
    -
    - ); - if (!critical && !major && !minor) { - vulnList =
    { this.mkTooltipVulnLine('secure') }
    ; - } - return ( -
    -
    COMPONENT
    -
    { `${component} ${version}` }
    - { vulnList } -
    - ); - } - - // Create line with square for inside tooltip, ex: `[] 4 Critical Vulnerabilities` - mkTooltipVulnLine = (severity, num) => { - if (!num && severity !== 'secure') { - return null; - } - const v = num === 1 ? `Vulnerability` : `Vulnerabilities`; - const squareClasses = classnames({ - [styles[severity]]: true, - [styles.tooltipSquare]: true - }); - const text = severity === 'secure' ? `No Known Vulnerabilities` : `${num} ${capitalize(severity)} ${v}`; - return ( -
    -   - { text } -
    - ); - } - - render() { - const { component, version } = this.props.component; - const tooltipId = `square-${component}-${version}`; - const tooltipContent = this.mkTooltipContent(); - const { isLayerSelected, isSelected, severity } = this.props; - const squareClasses = classnames({ - [styles.square]: true, - //layer is not selected or this component is selected - [styles.solid]: !isLayerSelected || isSelected, - //another component is selected - [styles.faded]: isLayerSelected && !isSelected, - [styles.outline]: isSelected, - [styles[severity]]: true - }); - return ( - -
    -   -
    -
    - ); - } -} diff --git a/app/scripts/components/repo/repo_details/scannedTag/selectors.js b/app/scripts/components/repo/repo_details/scannedTag/selectors.js deleted file mode 100644 index ddfdd32924..0000000000 --- a/app/scripts/components/repo/repo_details/scannedTag/selectors.js +++ /dev/null @@ -1,85 +0,0 @@ -'use strict'; - -import { Map } from 'immutable'; -import { createSelector } from 'reselect'; -import { mapCvss, getHighestSeverity } from '../nautilusUtils.js'; -import values from 'lodash/object/values'; -import forEach from 'lodash/collection/forEach'; - - -// Returns the specific tag's scan for the current route -export const getScan = state => { - // When requesting the scan from the API we only ever get one scan back. - // This means that to get our scan we use the first value in our scan object. - // TODO: When we move to redux-simple-router we can use the router's state - // to create the object key as you'd expect. - const vals = values(state.scans.get('scan', new Map()).toJS()); - if (vals.length === 0) { - return null; - } - return vals[0]; -}; - -export const getVulnerabilities = (state) => - state.scans.get('vulnerability', new Map()).toJS(); - -export const getComponents = (state) => - state.scans.get('component', new Map()).toJS(); - -export const getLayers = (state) => - state.scans.get('blob', new Map()).toJS(); - -/** - * Returns a JS object containing component keys sorted into severity adjectives - * @return object {critical: [CompKey, CompKey], major: [], minor: [], secure: []} - */ -export const getComponentsBySeverity = createSelector( - [getComponents, getVulnerabilities], - (comps, vulns) => { - let map = { - critical: [], - major: [], - minor: [], - secure: [] - }; - //for each component in this scan get all the vulnerability cvss scores in an array - //and return the highest - forEach(comps, (componentDetail, componentKey) => { - //componentDetail.vulnerabilities is either null or has vuln keys - const { vulnerabilities } = componentDetail; - if (vulnerabilities === null || !vulnerabilities.length) { - map.secure.push(componentKey); - } else { - let cvssScores = []; - forEach(vulnerabilities, (v) => { - cvssScores.push(vulns[v].cvss); - }); - map[getHighestSeverity(...cvssScores)].push(componentKey); - } - }); - return map; - } -); - -/** - * Returns a JS object containing layer.index as keys (sha is not unique), - * with an object containing only that layer's vulnerabilities as the value. - * The object with vulnerabilies will be a subset of all vulnerabilities - * @return object { 0: [Vuln, Vuln], 1: [Vuln], ... } - */ -export const getVulnerabilitiesByLayer = createSelector( - [getLayers, getComponents, getVulnerabilities], - (layers, components, vulnerabilities) => { - let map = {}; - forEach(layers, l => { - let layerVulnerabilities = {}; - forEach(l.components, c => { - forEach(components[c].vulnerabilities, v => { - layerVulnerabilities[v] = vulnerabilities[v]; - }); - }); - map[l.index] = layerVulnerabilities; - }); - return map; - } -); diff --git a/app/scripts/components/repo/repo_details/tags/DeleteTagArea.css b/app/scripts/components/repo/repo_details/tags/DeleteTagArea.css deleted file mode 100644 index fda8ff4288..0000000000 --- a/app/scripts/components/repo/repo_details/tags/DeleteTagArea.css +++ /dev/null @@ -1,22 +0,0 @@ -@import "dux/css/box.css"; -@import "dux/css/colors.css"; - -.confirmDelete { - color: var(--primary-5); -} -.confirmDelete:hover { - color: color(var(--primary-5) blackness(15%)); -} - -.delete { - color: var(--secondary-5); - transition: color .15s ease-in-out; - align-self: center; -} -.delete:hover { - color: var(--primary-5); -} - -.error { - color: var(--primary-5); -} diff --git a/app/scripts/components/repo/repo_details/tags/DeleteTagArea.jsx b/app/scripts/components/repo/repo_details/tags/DeleteTagArea.jsx deleted file mode 100644 index 4eb3ecff56..0000000000 --- a/app/scripts/components/repo/repo_details/tags/DeleteTagArea.jsx +++ /dev/null @@ -1,70 +0,0 @@ -'use strict'; - -import React, { PropTypes, Component } from 'react'; -import { ATTEMPTING, ERROR } from 'reduxConsts'; -const { func, instanceOf } = PropTypes; -import styles from './DeleteTagArea.css'; -import FA from 'common/FontAwesome'; -import { StatusRecord } from 'records'; -const debug = require('debug')('hub:deleteTagArea'); - -export default class DeleteTagArea extends Component { - // default status comes from StatusRecord - static propTypes = { - status: instanceOf(StatusRecord), - deleteTag: func - } - - state = { - confirmingDelete: false - } - - confirmDelete = (e) => { - this.setState({ - confirmingDelete: true - }); - } - - cancelConfirm = () => { - this.setState({ - confirmingDelete: false - }); - } - - render() { - const { deleteTag, status: { status } } = this.props; - const { confirmingDelete } = this.state; - let content; - if (status === ERROR) { - content = ( -
    - Deletion Failed -
    - ); - } else if (status === ATTEMPTING) { - content = ( -
    - Deleting  -
    - ); - } else if (confirmingDelete) { - content = ( - - ); - } else { - content = ( - - - - ); - } - return content; - } -} diff --git a/app/scripts/components/repo/repo_details/tags/ErrorBar.css b/app/scripts/components/repo/repo_details/tags/ErrorBar.css deleted file mode 100644 index 0faaf05e1d..0000000000 --- a/app/scripts/components/repo/repo_details/tags/ErrorBar.css +++ /dev/null @@ -1,9 +0,0 @@ -@import 'dux/css/colors.css'; - -.bar { - height: 100%; - width: 100%; - display: inline-block; - background-color: var(--iron); - user-select: none; -} diff --git a/app/scripts/components/repo/repo_details/tags/ErrorBar.jsx b/app/scripts/components/repo/repo_details/tags/ErrorBar.jsx deleted file mode 100644 index f277767452..0000000000 --- a/app/scripts/components/repo/repo_details/tags/ErrorBar.jsx +++ /dev/null @@ -1,10 +0,0 @@ -'use strict'; - -import React, { PropTypes, Component } from 'react'; -import styles from './ErrorBar.css'; - -export default class ErrorBar extends Component { - render() { - return
     
    ; - } -} diff --git a/app/scripts/components/repo/repo_details/tags/InProgressBar.css b/app/scripts/components/repo/repo_details/tags/InProgressBar.css deleted file mode 100644 index 29bb491b77..0000000000 --- a/app/scripts/components/repo/repo_details/tags/InProgressBar.css +++ /dev/null @@ -1,9 +0,0 @@ -@import 'dux/css/colors.css'; - -.gradient { - height: 100%; - width: 100%; - display: inline-block; - user-select: none; - background-image: repeating-linear-gradient(-45deg, var(--iron), var(--iron) 12px, var(--base) 0, var(--base) 24px); -} diff --git a/app/scripts/components/repo/repo_details/tags/InProgressBar.jsx b/app/scripts/components/repo/repo_details/tags/InProgressBar.jsx deleted file mode 100644 index 85be1df782..0000000000 --- a/app/scripts/components/repo/repo_details/tags/InProgressBar.jsx +++ /dev/null @@ -1,10 +0,0 @@ -'use strict'; - -import React, { PropTypes, Component } from 'react'; -import styles from './InProgressBar.css'; - -export default class InProgressBar extends Component { - render() { - return
     
    ; - } -} diff --git a/app/scripts/components/repo/repo_details/tags/ScannedTagRow.css b/app/scripts/components/repo/repo_details/tags/ScannedTagRow.css deleted file mode 100644 index 5ae99cd0c0..0000000000 --- a/app/scripts/components/repo/repo_details/tags/ScannedTagRow.css +++ /dev/null @@ -1,41 +0,0 @@ -.lineSpacing { - line-height: 1rem; -} - -.linePadding { - padding-bottom: 0.5rem; -} - -.smallText { - font-size: 0.9rem; -} - -.green { - color: #7DCCC0; -} - -.grey { - color: #7A8492; -} - -.icon { - margin-right: 0.5rem; -} - -.tagSize { - composes: lineSpacing; - composes: smallText; - color: #CECED9; -} - -.tagName { - composes: lineSpacing; - margin-right: 0.5rem; - font-size: 1.2rem; -} - - -.vulnerabilityBarWrapper { - height: 1rem; - width: 350px; -} diff --git a/app/scripts/components/repo/repo_details/tags/ScannedTagRow.jsx b/app/scripts/components/repo/repo_details/tags/ScannedTagRow.jsx deleted file mode 100644 index 77f7379be5..0000000000 --- a/app/scripts/components/repo/repo_details/tags/ScannedTagRow.jsx +++ /dev/null @@ -1,174 +0,0 @@ -'use strict'; - -import React, { PropTypes, Component } from 'react'; -import { Link } from 'react-router'; -const { func, object, shape, string, number, bool, instanceOf } = PropTypes; -import DeleteTagArea from './DeleteTagArea'; -import { FlexRow, FlexItem } from 'common/FlexTable.jsx'; -import VulnerabilityBar from './VulnerabilityBar'; -import InProgressBar from './InProgressBar'; -import ErrorBar from './ErrorBar'; -import bytesToSize from '../../../utils/bytesToSize'; -const debug = require('debug')('ScannedTagRow'); -import FontAwesome from 'common/FontAwesome'; -import classnames from 'classnames'; -import styles from './ScannedTagRow.css'; -import { StatusRecord } from 'records'; -import moment from 'moment'; -import { consts } from '../nautilusUtils'; - -//Renders a tag row for the Tags table with Nautilus Scan information -export default class ScannedTagRow extends Component { - - static propTypes = { - actions: shape({ - deleteRepoTag: func - }), - - tag: shape({ - name: string.isRequired, - full_size: number, - critical: number, - healthy: number, - major: number, - minor: number - }), - JWT: string.isRequired, - name: string.isRequired, - namespace: string.isRequired, - canEdit: bool.isRequired, - status: instanceOf(StatusRecord) - } - - static defaultProps = { - canEdit: false - } - - deleteTag = (e) => { - const { JWT, name, namespace, tag, actions } = this.props; - const tagName = tag.name; - actions.deleteRepoTag({ JWT, namespace, name, tagName }); - } - - render = () => { - const { - tag, - canEdit, - namespace, - name: repoName, - status - } = this.props; - const { - name, - full_size, - last_scanned, - critical, - healthy: secure, - major, - minor, - latest_scan_status - } = tag; - // this is the default value, indicating that no scan results exist - const isFirstScan = moment(last_scanned).isSame('0001-01-01T00:00:00Z'); - // A scan is in progress or failed but we have stale results to show - const scanInProgress = latest_scan_status === consts.IN_PROGRESS && !isFirstScan; - // A scan is in progress or failed and we don't have prior results to show - const newScanInProgress = latest_scan_status === consts.IN_PROGRESS && isFirstScan; - const newScanFailed = latest_scan_status === consts.FAILED && isFirstScan; - - const numVulnerableComponents = critical + major + minor; - const vulnerabilityTextClass = classnames({ - [styles.lineSpacing]: true, - [styles.grey]: true - }); - const vulnerabilityIconClass = classnames({ - [styles.lineSpacing]: true, - [styles.green]: !numVulnerableComponents, - [styles.grey]: numVulnerableComponents || newScanInProgress || newScanFailed, - [styles.icon]: true - }); - let icon, text, bar, lastScanned, titleLink; - if (newScanInProgress) { - icon = 'fa-refresh'; - text = `Scanning image for vulnerabilities...`; - bar = ; - lastScanned = `Scan in progress...`; - titleLink = name; - } else if (newScanFailed) { - icon = 'fa-minus-circle'; - text = `Could not complete image scan`; - bar = ; - lastScanned = `Scan failed`; - titleLink = name; - } else { - const numVulns = numVulnerableComponents ? 'vulnerabilities' : 'no known vulnerabilities'; - text = `This image has ${numVulns}`; - icon = numVulnerableComponents ? 'fa-exclamation-circle' : 'fa-check'; - bar = ( - - ); - //Do not expose refresh scanner failure if scan results exist - lastScanned = scanInProgress ? `New scan in progress...` : `Scanned ${moment(last_scanned).fromNow()}`; - titleLink = {name}; - } - const vulnerabilityArea = ( -
    -
    - - - - - {text} - -
    -
    - {bar} -
    -
    - ); - const lastScannedClasses = classnames({ - [styles.lineSpacing]: true, - [styles.smallText]: true, - [styles.grey]: true - }); - const tagNameClasses = classnames({ - [styles.tagName]: true, - [styles.grey]: newScanInProgress || newScanFailed - }); - const titleArea = ( -
    -
    - - {titleLink} - - - Compressed size: {bytesToSize(full_size)} - -
    -
    - {lastScanned} -
    -
    - ); - let deleteArea; - if (canEdit) { - deleteArea = ( - - ); - } - - return ( - - {titleArea} - {vulnerabilityArea} - {deleteArea} - - ); - } -} diff --git a/app/scripts/components/repo/repo_details/tags/UnscannedTagRow.jsx b/app/scripts/components/repo/repo_details/tags/UnscannedTagRow.jsx deleted file mode 100644 index 5baac35de8..0000000000 --- a/app/scripts/components/repo/repo_details/tags/UnscannedTagRow.jsx +++ /dev/null @@ -1,72 +0,0 @@ -'use strict'; -import React, { PropTypes, Component } from 'react'; -const { func, object, shape, string, number, bool, instanceOf } = PropTypes; -import DeleteTagArea from './DeleteTagArea'; -import { FlexRow, FlexItem } from 'common/FlexTable.jsx'; -import bytesToSize from '../../../utils/bytesToSize'; -const debug = require('debug')('UnscannedTagRow'); -import { StatusRecord } from 'records'; -import moment from 'moment'; - -//Renders a tag row for the Tags table that does not have Nautilus Scan information -export default class UnscannedTagRow extends Component { - static propTypes = { - actions: shape({ - deleteRepoTag: func - }), - - tag: shape({ - name: string.isRequired, - full_size: number - }), - JWT: string.isRequired, - name: string.isRequired, - namespace: string.isRequired, - canEdit: bool.isRequired, - status: instanceOf(StatusRecord) - } - - static defaultProps = { - canEdit: false - } - - deleteTag = (e) => { - const { JWT, name, namespace, tag } = this.props; - const tagName = tag.name; - this.props.actions.deleteRepoTag({ JWT, namespace, name, tagName }); - } - - render() { - const { - tag, - canEdit, - namespace, - name: repoName, - status - } = this.props; - const { name, full_size, last_updated } = tag; - - let deleteArea; - if (canEdit) { - deleteArea = ( - - ); - } - - const lastUpdated = last_updated ? moment(last_updated).fromNow() : `Unavailable`; - - return ( - - {name} - {bytesToSize(full_size)} - {lastUpdated} - - {deleteArea} - - - ); - } -} diff --git a/app/scripts/components/repo/repo_details/tags/VulnerabilityBar.jsx b/app/scripts/components/repo/repo_details/tags/VulnerabilityBar.jsx deleted file mode 100644 index 7baff85afa..0000000000 --- a/app/scripts/components/repo/repo_details/tags/VulnerabilityBar.jsx +++ /dev/null @@ -1,65 +0,0 @@ -'use strict'; - -import React, { PropTypes, Component } from 'react'; -const { number } = PropTypes; - -export default class VulnerabilityBar extends Component { - static propTypes = { - critical: number, - secure: number, - major: number, - minor: number - } - - getStyle = (severity, num, total) => { - const colors = { - critical: `#E8404B`, - major: `#FD854E`, - minor: `#FED954`, - secure: `#7DCCC0` - }; - - let width; - if (total) { - width = num / total * 100; - } else if (severity === 'secure'){ - width = 100; - } else { - width = 0; - } - - return { - width: `${width}%`, - backgroundColor: colors[severity], - display: `inline-block`, - height: `100%`, - userSelect: 'none' - }; - - } - - render() { - const { - critical, - secure, - major, - minor - } = this.props; - const total = critical + secure + major + minor; - const criticalStyle = this.getStyle('critical', critical, total); - const majorStyle = this.getStyle('major', major, total); - const minorStyle = this.getStyle('minor', minor, total); - const secureStyle = this.getStyle('secure', secure, total); - const wrapperStyle = { width: `100%` }; - - return ( -
    -
     
    -
     
    -
     
    -
     
    -
    - ); - - } -} diff --git a/app/scripts/components/repo/repo_details/tags/selectors.js b/app/scripts/components/repo/repo_details/tags/selectors.js deleted file mode 100644 index 07cc2e5104..0000000000 --- a/app/scripts/components/repo/repo_details/tags/selectors.js +++ /dev/null @@ -1,65 +0,0 @@ -'use strict'; - -import { createSelector } from 'reselect'; -import { Map, List } from 'immutable'; -import filter from 'lodash/collection/filter'; -import size from 'lodash/collection/size'; -import map from 'lodash/collection/map'; -import values from 'lodash/object/values'; - - -// Returns all repository tags (unordered) -export const getRepoTags = (state) => { - const reponame = state.repos.get('name', ''); - const namespace = state.repos.get('namespace', ''); - // We need to use toJS() to deeply convert tags from immutable to objects. - // We also return an array because getScannedTags and getUnscannedTags return - // arrays - keeping things consistent. - return values(state.tags.getIn([namespace, reponame, 'tags'], new Map()).toJS()); -}; - -// Returns all repository tags in the order of the hub API -// Note: This does _not_ return any tags that are returned by nautilus but not hub -// so we use the getRepoTags for the scannedTag selector -export const getRepoTagsInOrder = (state) => { - const reponame = state.repos.get('name', ''); - const namespace = state.repos.get('namespace', ''); - // We need to use toJS() to deeply convert tags from immutable to objects. - // We also return an array because getScannedTags and getUnscannedTags return - // arrays - keeping things consistent. - let orderedTags = state.tags.getIn([namespace, reponame, 'result'], []); - if (orderedTags.toArray) { - orderedTags = orderedTags.toArray(); - } - const tags = state.tags.getIn([namespace, reponame, 'tags'], new Map()).toJS(); - return map(orderedTags, (tagId) => tags[tagId]); -}; - - -// Returns only tags which have been scanned by nautilus -export const getScannedTags = createSelector( - [getRepoTags], - (tags) => { - // If the tag has a 'healthy' key then this has been scanned by nautilus - return filter(tags, (tag) => tag.healthy !== undefined); - } -); -// Number of tags scanned by nautilus -export const getScannedTagCount = createSelector( - [getScannedTags], - (tags) => size(tags) -); - -// getUnscannedTags returns only tags **not** scanned by nautilus -export const getUnscannedTags = createSelector( - [getRepoTagsInOrder], - (tags) => { - // If healthy is undefined this tag only has a hub response - return filter(tags, (tag) => tag.healthy === undefined); - } -); - -export const getUnscannedTagCount = createSelector( - [getUnscannedTags], - (tags) => size(tags) -); diff --git a/app/scripts/components/repo/store-promotion.js b/app/scripts/components/repo/store-promotion.js deleted file mode 100644 index 13645dc176..0000000000 --- a/app/scripts/components/repo/store-promotion.js +++ /dev/null @@ -1,106 +0,0 @@ -'use strict'; - -module.exports = { - STORE_OFFICIAL_REPONAME_ID_MAP: { - busybox: '061eb9c1-aeec-4ec8-8c4b-ba30ae1d5b47', - telegraf: 'f031f47c-6f88-4c21-a31a-20be46809d37', - consul: 'fec1f6b9-0a26-49b7-990b-d001a3496cc6', - sourcemage: '983e7005-65f1-4ff0-833e-a2edce972d88', - nuxeo: '139c1693-dc39-42cd-8104-cdf838504954', - mysql: '3083290a-203f-4c04-b2de-cc057959d2c9', - piwik: '40157634-cee7-462f-9927-27d734de3a28', - ros: '4e84c2be-5bb3-40f8-8854-8901e496d576', - 'buildpack-deps': '9e56c286-5b40-4838-89fe-fd513c9c3bd6', - 'hello-world': 'f35b81c7-b96a-45d3-809d-99eef381e71f', - sonarqube: '3f8fc4ce-eb8e-40ad-88ba-69e97299c64f', - celery: '4a239159-e3cf-42b1-b16f-6a9a8555285f', - neurodebian: '63dbd2e1-f29e-498b-8b16-1477770ae733', - glassfish: '4dfbd2c4-46dd-4674-8595-433594514a69', - erlang: '06fabd5a-6420-4209-a756-3d3355b3c672', - cirros: 'e3d3b771-35d3-45fe-92af-3f8bbd56cb40', - postgres: '022689bf-dfd8-408f-9e1c-19acac32e57b', - python: '1ae86987-df14-4741-9433-d9602a4da995', - crux: '8319429c-874d-4cfa-9dde-b861f7245eab', - pypy: '91db8014-64b0-4417-9429-e8128e04191c', - alpine: 'e7e5dbc4-2103-4b7c-9409-b0ca32ce3d83', - memcached: 'deec12eb-5792-49d2-919e-0b861bb910cd', - rabbitmq: 'fa7625b4-fdca-4b48-b078-692f6451965a', - orientdb: '7a741b7c-b96a-44ce-b64d-d0b59e6a7803', - chronograf: 'c3749997-031b-4ced-9f0b-cb4d15b6a6a1', - centos: 'd5052416-4069-4619-8597-ba61df35ba6f', - hipache: '12bafabf-353e-47ad-a416-44d827874489', - kibana: '41105537-6820-4448-908b-4ac7b31be0c2', - 'websphere-liberty': 'cacdc40b-0fed-4221-952a-18b0b8a3500b', - redis: '1f6ef28b-3e48-4da1-b838-5bd8710a2053', - 'mongo-express': 'e89a86ce-9988-4ee1-ada9-228925730018', - lightstreamer: 'b0766515-2ca5-4ea2-9120-713cab78d0f7', - gazebo: 'e42e1e00-1168-4815-b951-6ee5bae86d58', - kapacitor: 'f310b81d-5c23-4936-880d-027ffe296557', - influxdb: '2053499a-fe59-495d-a024-518311223f3f', - maven: '3e44be96-02cf-427e-bdbe-f108ec3be831', - odoo: 'f351cb39-4574-44e7-afa6-b3cc87390041', - notary: '7cb50ac7-d119-4ec7-a276-cad5154fb67e', - solr: 'f4e3929d-d8bc-491e-860c-310d3f40fff2', - logstash: '6464c97c-8e9c-492c-8a35-27620300a6cc', - thrift: '579aa075-9d28-4ae5-9966-357b96f70550', - haproxy: '85c386ff-85a7-4d61-b309-5901f625c36f', - drupal: '680b2b97-bc91-44fc-9437-73748b0a8f0a', - mono: '4234a761-444b-4dea-a6b3-31bda725c427', - joomla: 'e17a7172-1f32-4191-83ba-606f354cce16', - elasticsearch: '1090e442-627e-4bf2-b29a-555f57a64ecd', - clojure: '800b3c7e-3b83-4af5-ab84-b57086887339', - 'rakudo-star': '2a6a7106-f60e-495a-b085-e0496e23b72e', - traefik: '0319de97-4b7f-4a74-a260-5d027ec8cee0', - elixir: '4e418a43-2be9-44fd-8640-9dbb82c369a2', - irssi: 'cb02bc13-349b-4aad-9b2e-6045c16d9c4c', - julia: 'b228ffc7-3d8c-46c5-9e2d-4101e2b9629a', - jruby: 'c90a0b81-88c5-437a-87b2-38c9a398451e', - haskell: '74b1a6b9-c84a-4221-891d-18d28f1798e5', - neo4j: '5f0be9a7-f5d7-4974-9c0e-78c33484e79c', - httpd: '3574ef8c-86e4-40ed-a705-3a52d9786bde', - php: '9c2c5426-0cca-4a30-a450-b2961541c6dc', - java: '199a18b1-511b-47fd-b287-a41555fafb9f', - bonita: 'c37b224a-dec9-4dbe-b18a-5f1789766409', - jetty: 'd88c12a5-0ca7-4358-aef0-c759b0e5290a', - rails: 'a3ed7866-8446-4221-b86d-67507eb6be3e', - perl: '5241d150-6793-4ca8-a392-51098722f672', - swarm: '8ea4fd22-82ac-4ec8-b89d-018cb0944d72', - redmine: 'dfd4330b-0b3a-479c-8bbc-8b4cad6235b8', - wordpress: 'c14a56d6-07e4-464b-b71c-4b24dc7f1836', - tomee: 'afc9cbe9-8325-4609-ad48-cc891f1e0002', - photon: '45053cf9-0044-46cc-9748-d6d01a548dd3', - 'r-base': 'f2e50720-cada-432f-85a5-1ade438d537b', - oraclelinux: '505eac14-101f-44de-b80f-d79743a2288d', - ruby: '0f900dcb-7e32-45e4-b095-6dfa2f5b597b', - iojs: 'c3a93fc8-ef57-47df-ad12-6e443cd93f61', - rethinkdb: '6e5e7f5d-52fa-4598-a8fc-f1911a873ac0', - mongo: '9147d1b7-a686-4e38-8ecd-94a47f5da9cf', - golang: '3e4f3e51-3930-4dd8-975c-517705d9d4e7', - mageia: '179f8859-4966-4750-a2a9-5cd203556556', - owncloud: 'a66e9029-57d7-4aef-89b0-a98987e8dbf2', - cassandra: '53ad54dd-9bd8-48cd-89b4-fc1d5fdfa6cc', - gcc: '06ad851d-f666-47d3-9ef3-e90535c141ec', - fedora: 'a5648d34-aacd-4599-ab72-79662aa09df2', - couchdb: '263ad544-d7c7-4892-8244-fe78b6231265', - arangodb: '806abe10-8cee-451b-856b-57bcf0fdf6d0', - jenkins: 'd55eda09-d7f0-47b0-8780-3407f2f9142c', - hylang: '62cb43d8-bf5b-4115-8408-ff1412ead82e', - node: 'e6658267-cc55-421e-b5be-5e69460fb0d1', - percona: '176b92e3-b122-422c-96f0-d518bffe9bd5', - registry: 'd93c7069-a612-4019-ade6-8c3b0a73acd9', - mariadb: '1712cb54-62e1-405b-a973-1492552c9bb9', - debian: '40efd176-3c0a-4460-9f94-fc98ca92362f', - ghost: '57aa97f1-9868-4936-906c-b83d78cfaf4f', - opensuse: '99f9bd45-4c65-4e45-aa36-234e9150efc6', - tomcat: '3d5f71ad-2cc0-467f-ab6a-351e7adf404e', - django: '65765d71-d893-407d-a707-486c7381dfbf', - backdrop: 'aa66b4ed-fd75-4a87-87a7-c173c740a42f', - docker: '995677a1-1f6a-4e2e-929a-fde926abbd95', - ubuntu: '414e13de-f1ba-40d0-9867-08f2e5884b3f', - nginx: '37b1dde7-a3e7-463a-a0e3-d8be2b136292', - sentry: '788f45b7-2701-4244-90e4-3f85aef116d8', - couchbase: '881296c9-606f-4861-91b6-26a31ef52618', - crate: 'dfac6fed-98d7-4c5d-b338-fb6930c62c69', - nats: '59c6aa2f-dcca-4f2c-8c30-2ea2326feab2' - } -}; diff --git a/app/scripts/components/repositories/AutoBuildSetupForm.css b/app/scripts/components/repositories/AutoBuildSetupForm.css deleted file mode 100644 index c078308f01..0000000000 --- a/app/scripts/components/repositories/AutoBuildSetupForm.css +++ /dev/null @@ -1,49 +0,0 @@ -@import "dux/css/box.css"; -@import "dux/css/colors.css"; - -.errorText { - white-space: pre; -} - -.input { - margin-right: var(--default-margin); -} - -.formContainer { - margin-top: var(--default-margin); -} - -.error { - color: var(--primary-5); - font-size: .875rem; - margin-bottom: 0.3rem; -} - -/* TODO: this is also used in EnterpriseTrialForm.css | a candidate to be in colors.css */ -.label { - color: #7a8491; - font-weight: 500; - sup { - font-size: 1rem; - vertical-align: text-bottom; - } -} - -.customizeLabel { - composes: label; - margin-bottom: 0.5rem; -} - -.floatRight { - float: right; - margin-right: 1rem; -} - -.globalError { - composes: error; - composes: floatRight; -} - -.select { - border-radius: var(--global-radius); -} \ No newline at end of file diff --git a/app/scripts/components/repositories/AutoBuildSetupForm.jsx b/app/scripts/components/repositories/AutoBuildSetupForm.jsx deleted file mode 100644 index 19d03c80af..0000000000 --- a/app/scripts/components/repositories/AutoBuildSetupForm.jsx +++ /dev/null @@ -1,410 +0,0 @@ -'use strict'; - -import React, { PropTypes } from 'react'; -import findIndex from 'lodash/array/findIndex'; -import includes from 'lodash/collection/includes'; -import omit from 'lodash/object/omit'; -import map from 'lodash/collection/map'; -import AutoBuildTagsInput from './AutoBuildTagsInput.jsx'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import RepositoryNameInput from 'common/RepositoryNameInput.jsx'; -import SimpleTextArea from 'common/SimpleTextArea.jsx'; -import AutobuildStore from '../../stores/AutobuildStore'; -import AutobuildConfigStore from '../../stores/AutobuildConfigStore'; -import AutobuildSourceRepositoriesStore from '../../stores/AutobuildSourceRepositoriesStore'; -import RepoStore from '../../stores/RepositoryPageStore'; -import UserStore from '../../stores/UserStore'; -import createAutobuild from '../../actions/createAutobuild'; -import updateAutobuildFormField from '../../actions/updateAutobuildFormField.js'; -import getSettingsData from 'actions/getSettingsData'; -import { PageHeader } from 'dux'; -import AlertBox from 'common/AlertBox'; -import Card, { Block } from '@dux/element-card'; -import Button from '@dux/element-button'; -import { validateRepositoryName } from '../utils/validateRepositoryName'; -import { STATUS as COMMONSTATUS } from '../../stores/common/Constants'; -import Markdown from '@dux/element-markdown'; - -const { - ATTEMPTING -} = COMMONSTATUS; - -const buildTagsClientSideError = 'No empty strings allowed for docker tag (or) source tag/branch name specification.'; - -import styles from './AutoBuildSetupForm.css'; - -const { - array, - bool, - func, - number, - object, - oneOf, - shape, - string -} = PropTypes; - -var AutoBuildSetupForm = React.createClass({ - contextTypes: { - executeAction: func.isRequired - }, - propTypes: { - user: object.isRequired, - JWT: string.isRequired, - ownedNamespaces: array.isRequired, - configStore: shape({ - description: string, - isPrivate: oneOf(['private', 'public']).isRequired, - name: string.isRequired, - namespace: string.isRequired, - sourceRepoName: string.isRequired, - STATUS: string.isRequired - }), - sourceRepositories: shape({ - type: string.isRequired - }) - }, - getInitialState: function() { - return { - isActive: true, - buildTags: this.defaultBuildTags, - clientSideError: '', - advancedMode: false - }; - }, - /*eslint-disable camelcase*/ - - /* - * By default, if the input is empty for source tag/branch name, send the string: '{sourceref}' & 'master' - * By default, if the input is empty for docker tag name, send the string with regex for all matches & 'latest' - */ - defaultBuildTags: [ - { - id: 'tag-0', - name: 'latest', - source_type: 'Branch', - source_name: 'master', - dockerfile_location: '/' - }, - { - id: 'tag-1', - name: '{sourceref}', - source_type: 'Branch', - source_name: '/^([^m]|.[^a]|..[^s]|...[^t]|....[^e]|.....[^r]|.{0,5}$|.{7,})/', - dockerfile_location: '/' - } - ], - getBuildTagsToSend: function() { - let bTags = this.state.buildTags; - return map(bTags, (tag) => { - return omit(tag, 'id'); - }); - }, - /*eslint-enable camelcase */ - _handleCreate: function(evt) { - evt.preventDefault(); - const { username } = this.props.user; - const { buildTags, isActive } = this.state; - const { description, isPrivate, name, namespace, sourceRepoName } = this.props.configStore; - const { type } = this.props.sourceRepositories; - - const params = this.props.params; - const sourceRepoFallback = `${params.sourceRepoNamespace}/${params.sourceRepoName}`; - - if (!validateRepositoryName(name.toLowerCase())) { - //check if the repo name is valid | client side check - this.setState({ - clientSideError: `No spaces and special characters other than '.' and '-' are allowed. -Repository names should not begin/end with a '.' or '-'.` - }); - } else { - - var newAutobuild = { - user: username, - namespace: namespace, - name: name.toLowerCase(), - description: description, - is_private: isPrivate === 'private', - build_name: sourceRepoName.toLowerCase() || sourceRepoFallback.toLowerCase(), - provider: type.toLowerCase(), - active: isActive, - tags: this.getBuildTagsToSend() - }; - - this.context.executeAction(createAutobuild, {JWT: this.props.JWT, autobuildConfig: newAutobuild}); - } - }, - _onActiveStateChange: function(e) { - this.setState({isActive: !this.state.isActive}); - }, - _getTagIndex: function(id) { - return findIndex(this.state.buildTags, function(tag) { - return (tag.id === id); - }); - }, - _setTagState: function(id, prop, value) { - let bTags = this.state.buildTags; - bTags[this._getTagIndex(id)][prop] = value; //find tag and update property - this.setState({ - buildTags: bTags - }); - }, - _onTagRemoved: function(id) { - //Remove tag, when user removes it from the form - let bTags = this.state.buildTags; - bTags.splice(this._getTagIndex(id), 1); - this.setState({ - buildTags: bTags - }); - }, - _onTagAdded: function(tag) { - let bTags = this.state.buildTags; - bTags.push(tag); - this.setState({ - buildTags: bTags - }); - }, - _resetBuildTagsError: function() { - //Reset clientSideError on change - if (this.state.clientSideError === buildTagsClientSideError) { - this.setState({ - clientSideError: '' - }); - } - }, - _onSourceNameChange: function(tagId, e) { - let sourceName = e.target.value; - let sourceType = this.state.buildTags[this._getTagIndex(tagId)].sourceType; - if (sourceName === '' && sourceType && sourceType === 'Branch') { - sourceName = '/^([^m]|.[^a]|..[^s]|...[^t]|....[^e]|.....[^r]|.{0,5}$|.{7,})/'; - } else if (sourceName === '' && sourceType && sourceType === 'Tag') { - sourceName = '/.*/'; - } else { - this._resetBuildTagsError(); - //Strip trailing and leading spaces. If we end up with empty string, throw an error. - if (sourceName.trim() === '') { - this.setState({ - clientSideError: buildTagsClientSideError - }); - } - } - this._setTagState(tagId, 'source_name', sourceName.trim()); - }, - _onSourceTypeChange: function(tagId, e) { - this._setTagState(tagId, 'source_type', e.target.value); - }, - _onDockerfileLocationChange: function(tagId, e) { - this._setTagState(tagId, 'dockerfile_location', e.target.value); - }, - _onTagChange: function(tagId, e) { - let tagName = e.target.value; - if (tagName === '') { - tagName = '{sourceref}'; - } - this._setTagState(tagId, 'name', tagName.trim()); - }, - _updateForm(fieldKey) { - return (e) => { - if (fieldKey === 'namespace') { - this.setState({ - currentNamespace: e.target.value - }); - this.context.executeAction(getSettingsData, { - JWT: this.props.JWT, - username: e.target.value, - repoType: 'autobuild' - }); - } else if (fieldKey === 'name' && this.state.clientSideError) { - this.setState({ - clientSideError: '' - }); - } - this.context.executeAction(updateAutobuildFormField, { - fieldKey, - fieldValue: e.target.value - }); - }; - }, - componentWillReceiveProps: function(nextProps) { - const { name, namespace, success, STATUS } = nextProps.configStore; - //If autobuild was created successfully - if (STATUS.SUCCESSFUL || success) { - this.props.history.pushState(null, `/r/${namespace}/${name.toLowerCase()}/`); - } - }, - customTagsConfig: function() { - this.setState({ - advancedMode: true, - buildTags: [] - }); - }, - defaultTagsConfig: function() { - this.setState({ - advancedMode: false, - buildTags: this.defaultBuildTags - }); - }, - render: function() { - - const { - description, - error, - isPrivate, - name, - namespace, - success, - STATUS - } = this.props.configStore; - - /* start error/success handling */ - let maybeSuccess = ; - if (success) { - maybeSuccess = {success}; - } - - let nameError; - let nameErrorContent = error.dockerhub_repo_name; - if(nameErrorContent) { - nameError = nameErrorContent; - } - - let descriptionError; - if(error.description) { - descriptionError = error.description; - } - - let privateRepoError; - if(error.is_private) { - privateRepoError = error.is_private; - } - - let buildTagsError; - if (error.buildTags) { - buildTagsError = error.buildTags; - } - - let maybeError = null; - let errorDetail = error.detail || this.state.clientSideError; - if (errorDetail) { - maybeError = ( -
    -
    - {errorDetail} -
    -
    - ); - } - /* end error handling */ - - //Check if user has passed in namespace as query | verify if they have access to it - let currentUserNamespace = this.props.location.query.namespace; - if (!includes(this.props.ownedNamespaces, currentUserNamespace)) { - //If they don't have access to the namespace set in the query param ? then fallback to default namespace - currentUserNamespace = this.props.user.namespace; - } - let tagsConfigList = null; - - if (this.state.advancedMode) { - tagsConfigList = ( -
    -
    -
    Customize Autobuild Tags
    - -
    - {buildTagsError} -
    - -
    - ); - } - - return ( -
    - -
    -
    - - -
    -
    -
    - -
    - {nameError} -
    - -
    -
    - -
    - {privateRepoError} -
    - -
    -
    - -
    - {descriptionError} -
    - - - {/* advanced mode */} - {tagsConfigList} -
    - {maybeError} -
    -
    - -
    -
    - - {maybeSuccess} -
    -
    -
    -
    -
    - ); - } -}); - -export default connectToStores(AutoBuildSetupForm, - [ - AutobuildSourceRepositoriesStore, - AutobuildConfigStore, - UserStore - ], - function({ getStore }, props){ - return { - sourceRepositories: getStore(AutobuildSourceRepositoriesStore).getState(), - configStore: getStore(AutobuildConfigStore).getState(), - ownedNamespaces: getStore(UserStore).getNamespaces() - }; - }); diff --git a/app/scripts/components/repositories/AutoBuildTagsInput.jsx b/app/scripts/components/repositories/AutoBuildTagsInput.jsx deleted file mode 100644 index c5b4c52e53..0000000000 --- a/app/scripts/components/repositories/AutoBuildTagsInput.jsx +++ /dev/null @@ -1,159 +0,0 @@ -'use strict'; - -import React from 'react'; -import { FlexTable, Header, Item } from 'common/TagsFlexTable'; -import AutoBuildTagsInputItem from './AutoBuildTagsInputItem.jsx'; - -const AutoBuildTagsInput = React.createClass({ - contextTypes: { - getStore: React.PropTypes.func.isRequired - }, - propTypes: { - repo: React.PropTypes.string.isRequired, - onTagRemoved: React.PropTypes.func.isRequired, - onTagAdded: React.PropTypes.func.isRequired, - onSourceTypeChange: React.PropTypes.func.isRequired, - onSourceNameChange: React.PropTypes.func.isRequired, - onDockerfileLocationChange: React.PropTypes.func.isRequired - }, - getInitialState: function() { - const masterDefaultRow = { - row: 'row-0', - sourceType: 'Branch', - sourceName: 'master', - sign: 'plus', - tag: 'latest', - fileLocation: '/', - tagId: 'tag-0' - }; - const dynamicTagRow = { - row: 'row-1', - sourceType: 'Branch', - sourceName: '', - sign: 'minus', - tag: '', - fileLocation: '/', - tagId: 'tag-1' - }; - return { - currentRows: [ - this.makeRow(masterDefaultRow), - this.makeRow(dynamicTagRow) - ] - }; - }, - _handleBtnClickAdd: function(e) { - e.preventDefault(); - let rows = this.state.currentRows; - let idx = this.state.currentRows.length; - const row = { - row: 'row-' + idx, - sourceType: 'Branch', - sourceName: '', - sign: 'minus', - tag: '', - fileLocation: '/', - tagId: 'tag-' + idx - }; - const newRow = this.makeRow(row); - this.setState({ - currentRows: rows.concat(newRow) - }); - //Make an empty build tag that will get updated on edit - const bTag = { - id: 'tag-' + idx, - sourceType: 'Branch', - sourceName: '', - fileLocation: '/', - tagName: '' - }; - this.props.onTagAdded(this.makeBuildTag(bTag)); - }, - makeRow: function(rowObj) { - const { - row, - sourceType, - sourceName, - sign, - tag, - fileLocation, - tagId - } = rowObj; - - return ( - - ); - }, - makeBuildTag: function(newBuildTag) { - const { - id, - sourceType, - sourceName, - fileLocation, - tagName - } = newBuildTag; - /*eslint-disable camelcase */ - /* By default, if the input is empty for source tag/branch name, send the string: '{sourceref}'*/ - /* By default, if the input is empty for docker tag name, send the string with the regex for all matches */ - return { - id: id, - name: tagName === '' ? '{sourceref}' : tagName, - source_type: sourceType, - source_name: sourceName === '' ? '/^([^m]|.[^a]|..[^s]|...[^t]|....[^e]|.....[^r]|.{0,5}$|.{7,})/' : sourceName, - dockerfile_location: fileLocation - }; - /*eslint-enable camelcase */ - }, - componentDidMount: function() { - const masterBuildTag = { - id: 'tag-0', - sourceType: 'Branch', - sourceName: 'master', - fileLocation: '/', - tagName: 'latest' - }; - const dynamicBuildTag = { - id: 'tag-1', - sourceType: 'Branch', - sourceName: '', - fileLocation: '/', - tagName: '' - }; - this.props.onTagAdded( - this.makeBuildTag(masterBuildTag) - ); - this.props.onTagAdded( - this.makeBuildTag(dynamicBuildTag) - ); - }, - render: function() { - return ( - -
    - Push Type - Name - Dockerfile Location - Docker Tag - -
    - { this.state.currentRows } -
    - ); - } -}); - -module.exports = AutoBuildTagsInput; diff --git a/app/scripts/components/repositories/AutoBuildTagsInputItem.css b/app/scripts/components/repositories/AutoBuildTagsInputItem.css deleted file mode 100644 index 754af1558e..0000000000 --- a/app/scripts/components/repositories/AutoBuildTagsInputItem.css +++ /dev/null @@ -1,28 +0,0 @@ -@import 'dux/css/colors.css'; -@import 'dux/css/box.css'; - -.faBtn { - cursor: pointer; - user-select: none; - margin-left: auto; - margin-right: auto; - margin-top: 0.8rem; -} - -.addBtn { - composes: faBtn; - color: var(--success-color); -} - -.removeBtn { - composes: faBtn; - color: var(--alert-color); -} - -.select { - border-radius: var(--global-radius); -} - -input.rounded { - border-radius: var(--global-radius); -} \ No newline at end of file diff --git a/app/scripts/components/repositories/AutoBuildTagsInputItem.jsx b/app/scripts/components/repositories/AutoBuildTagsInputItem.jsx deleted file mode 100644 index 17a1cb06f9..0000000000 --- a/app/scripts/components/repositories/AutoBuildTagsInputItem.jsx +++ /dev/null @@ -1,123 +0,0 @@ -'use strict'; - -import React, {PropTypes} from 'react'; -import { Row, Header, Item } from 'common/TagsFlexTable'; -import FA from 'common/FontAwesome'; -import styles from './AutoBuildTagsInputItem.css'; -import Button from '@dux/element-button'; -const {func, string} = PropTypes; - -const AutoBuildTagsInputItem = React.createClass({ - propTypes: { - row: string.isRequired, - sign: string.isRequired, - tagId: string.isRequired, - tagName: string.isRequired, - removeItem: func.isRequired, - sourceName: string.isRequired, - sourceType: string.isRequired, - fileLocation: string.isRequired, - handleBtnClick: func.isRequired, - onSourceTypeChange: func.isRequired, - onSourceNameChange: func.isRequired, - onTagChange: func.isRequired, - onDockerfileLocationChange: func.isRequired - }, - getInitialState: function() { - return { - hidden: false, - sourceType: 'Branch' - }; - }, - _handleHide: function(e) { - e.preventDefault(); - e.stopPropagation(); - this.setState({ - hidden: true - }); - this.props.removeItem(this.props.tagId); - }, - onSourceTypeChange: function(e) { - this.setState({ - sourceType: e.target.value - }); - this.props.onSourceTypeChange(e); - }, - componentDidMount: function() { - this.setState({ - tag: this.props.tagName - }); - }, - render: function() { - - let sourceNamePlaceholder; - let tagNamePlaceholder; - - //Support to show default rule for each type of rule in the UI - const branchesOrTags = this.state.sourceType === 'Branch' ? 'branches' : 'tags'; - const branchOrTag = this.state.sourceType === 'Branch' ? 'branch' : 'tag'; - if (this.state.sourceType === 'Branch') { - sourceNamePlaceholder = 'All branches except master'; - } else { - sourceNamePlaceholder = '/.*/ This targets all tags'; - } - tagNamePlaceholder = `Same as ${branchOrTag}`; - - const { - fileLocation, - handleBtnClick, - onDockerfileLocationChange, - onTagChange, - onSourceNameChange, - row, - sign, - sourceName, - sourceType, - tagName - } = this.props; - - let item = null; - if (!this.state.hidden) { - item = ( - - - - - - - - - - - - - - - - - - - - ); - } - - return item; - } -}); - -module.exports = AutoBuildTagsInputItem; diff --git a/app/scripts/components/repositories/Autobuild.jsx b/app/scripts/components/repositories/Autobuild.jsx deleted file mode 100644 index 5b8d7cf080..0000000000 --- a/app/scripts/components/repositories/Autobuild.jsx +++ /dev/null @@ -1,102 +0,0 @@ -'use strict'; - -import AutobuildStore from '../../stores/AutobuildStore'; -import Route404 from '../common/RouteNotFound404Page.jsx'; -import AutobuildBlankSlate from './AutobuildBlankSlate.jsx'; -import React, { PropTypes, cloneElement } from 'react'; -import { Link } from 'react-router'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import { SecondaryNav } from 'dux'; -import LiLink from '../common/LiLink'; -const debug = require('debug')('COMPONENT:Autobuild'); - -let AutobuildSourcesNav = React.createClass({ - displayName: 'AutobuildSourcesNav', - propTypes: { - namespace: PropTypes.string, - githubAccount: PropTypes.object, - bitbucketAccount: PropTypes.object - }, - _checkAccountsAndGetLinks: function() { - var liLinks = []; - if (this.props.githubAccount) { - liLinks.push( - - GitHub ({this.props.githubAccount.login}) - ); - } - - if (this.props.bitbucketAccount) { - liLinks.push( - - Bitbucket ({this.props.bitbucketAccount.login}) - ); - } - - if (!this.props.githubAccount || !this.props.bitbucketAccount) { - liLinks.push( Link Accounts); - } - - return liLinks; - }, - render: function() { - var liLinks = this._checkAccountsAndGetLinks(); - return ( -
    - -
      - {liLinks} -
    -
    -
    - ); - } -}); - -var Autobuild = React.createClass({ - propTypes: { - user: React.PropTypes.object, - JWT: React.PropTypes.string - }, - contextTypes: { - executeAction: React.PropTypes.func.isRequired - }, - render: function() { - if (!this.props.JWT) { - return ( - - ); - } else if (!this.props.githubAccount && !this.props.bitbucketAccount) { - return ( -
    - - -
    - ); - } else { - return ( -
    - - {this.props.children && cloneElement(this.props.children, { - user: this.props.user, - JWT: this.props.JWT, - githubAccount: this.props.githubAccount, - bitbucketAccount: this.props.bitbucketAccount - })} -
    - ); - } - } -}); - -export default connectToStores(Autobuild, - [ - AutobuildStore - ], - function({ getStore }, props) { - return getStore(AutobuildStore).getState(); - }); diff --git a/app/scripts/components/repositories/AutobuildBlankSlate.css b/app/scripts/components/repositories/AutobuildBlankSlate.css deleted file mode 100644 index 7de08e056a..0000000000 --- a/app/scripts/components/repositories/AutobuildBlankSlate.css +++ /dev/null @@ -1,6 +0,0 @@ -@import "dux/css/box.css"; -@import "dux/css/colors.css"; - -.row { - margin-top: var(--default-margin); -} diff --git a/app/scripts/components/repositories/AutobuildBlankSlate.jsx b/app/scripts/components/repositories/AutobuildBlankSlate.jsx deleted file mode 100644 index df12b31f36..0000000000 --- a/app/scripts/components/repositories/AutobuildBlankSlate.jsx +++ /dev/null @@ -1,41 +0,0 @@ -'use strict'; - -import React, { PropTypes } from 'react'; -import Card, { Block } from '@dux/element-card'; -import FA from 'common/FontAwesome'; -import styles from './AutobuildBlankSlate.css'; -import { Link } from 'react-router'; - -var AutobuildBlankSlate = React.createClass({ - displayName: 'AutobuildBlankSlate', - propTypes: { - slateItems: React.PropTypes.element - }, - render() { - var slateItems = null; - if (!this.props.slateItems) { - slateItems = ( -
    -

    You haven't linked to GitHub or Bitbucket yet.

    - Link Accounts -
    - ); - } else { - slateItems = this.props.slateItems; - } - - return ( -
    -
    - - - {slateItems} - - -
    -
    - ); - } -}); - -module.exports = AutobuildBlankSlate; diff --git a/app/scripts/components/repositories/AutobuildIndex.css b/app/scripts/components/repositories/AutobuildIndex.css deleted file mode 100644 index 4059a66e80..0000000000 --- a/app/scripts/components/repositories/AutobuildIndex.css +++ /dev/null @@ -1,28 +0,0 @@ -@import "dux/css/box.css"; -@import "dux/css/colors.css"; - -.row { - margin-top: var(--default-margin); -} - -.link { - display: block; - background: white; - border-radius: var(--global-radius); - border: 1px solid var(--silver); - color: var(--secondary-4); - margin: 0 .3rem .3rem 0; - padding: 1.8rem; - i { - font-size: 6rem; - margin-bottom: 1rem; - } - &:hover { - background: #f4f9fc; - color: var(--secondary-4); - } - &:focus { - background: color(#f4f9fc blackness(10%)); - color: var(--secondary-4); - } -} diff --git a/app/scripts/components/repositories/AutobuildIndex.jsx b/app/scripts/components/repositories/AutobuildIndex.jsx deleted file mode 100644 index 23158f62e7..0000000000 --- a/app/scripts/components/repositories/AutobuildIndex.jsx +++ /dev/null @@ -1,67 +0,0 @@ -'use strict'; - -import React, { PropTypes, Component } from 'react'; -import { Link } from 'react-router'; -import FA from 'common/FontAwesome'; -import classnames from 'classnames'; -import styles from './AutobuildIndex.css'; - -export default class AutobuildIndex extends Component { - static propTypes = { - githubAccount: PropTypes.object, - bitbucketAccount: PropTypes.object - } - - render() { - let githubText; - let githubLink; - let bitbucketText; - let bitbucketLink; - const linkClasses = classnames({ - 'button': true, - [styles.link]: true - }); - - if (this.props.githubAccount) { - githubLink = `/add/automated-build/${this.props.params.userNamespace}/github/orgs/`; - githubText = ( -

    Create Auto-build

    - ); - } else { - githubLink = '/account/authorized-services/'; - githubText = ( -

    Link Account

    - ); - } - if (this.props.bitbucketAccount) { - bitbucketLink = `/add/automated-build/${this.props.params.userNamespace}/bitbucket/orgs/`; - bitbucketText = ( -

    Create Auto-build

    - ); - } else { - bitbucketLink = '/account/authorized-services/'; - bitbucketText = ( -

    Link Account

    - ); - } - - return ( -
    -
    - - {githubText} - -

    Github

    - -
    -
    - - {bitbucketText} - -

    Bitbucket

    - -
    -
    - ); - } -} diff --git a/app/scripts/components/repositories/LinkedAccountSourcesForm.css b/app/scripts/components/repositories/LinkedAccountSourcesForm.css deleted file mode 100644 index 32e2acd73a..0000000000 --- a/app/scripts/components/repositories/LinkedAccountSourcesForm.css +++ /dev/null @@ -1,3 +0,0 @@ -.arrowSelect { - margin-top: 0.3rem; -} \ No newline at end of file diff --git a/app/scripts/components/repositories/LinkedAccountSourcesForm.jsx b/app/scripts/components/repositories/LinkedAccountSourcesForm.jsx deleted file mode 100644 index 4ba18daac6..0000000000 --- a/app/scripts/components/repositories/LinkedAccountSourcesForm.jsx +++ /dev/null @@ -1,163 +0,0 @@ -'use strict'; -import React, { Component, PropTypes } from 'react'; -import { Link } from 'react-router'; -import _ from 'lodash'; -import AutobuildBlankSlate from './AutobuildBlankSlate.jsx'; -import AutobuildSourceRepositoriesStore from '../../stores/AutobuildSourceRepositoriesStore'; -import selectSourceRepoForAutobuild from '../../actions/selectSourceRepoForAutobuild'; -import ListSelector from '../common/ListSelector.jsx'; -import FilterBar from '../filter/FilterBar.jsx'; -import FA from 'common/FontAwesome'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import styles from './LinkedAccountSourcesForm.css'; - -const debug = require('debug')('COMPONENT:LinkedAccountSourcesForm'); -const { array, func } = PropTypes; - -class LinkedAccountSourcesForm extends Component{ - - static propTypes = { - repos: array - } - - static contextTypes = { - executeAction: func.isRequired - } - - state = { - selectedRepos: [], - selectedUserOrg: {} - } - - _handleUserOrgClick = (userOrOrg) => { - //Clicked on user or org, show the repositories under that user or organization - this.setState({ - selectedUserOrg: userOrOrg, - selectedRepos: userOrOrg.repo_list - }); - } - - _handleRepoClick = (item, currentType) => { - //Replace all "/" with "-" if they exist, so route is always valid - item.name = item.name.replace(/[/]/g, '-'); - this.props.history.pushState(null, - `/add/automated-build/${currentType.toLowerCase()}/form/${this.state.selectedUserOrg.name}/${item.name}/`, - {namespace: this.props.params.userNamespace} - ); - //Set the source repository in the store, so the autobuild configuration form can get to it - this.context.executeAction(selectSourceRepoForAutobuild, item); - } - - _makeUserOrgList = (list) => { - var userAndOrgsList = list.map(function(item, idx) { - var imgAvatar = item.avatar_url; - var selectedArrow; - if (this.state.selectedUserOrg.name === item.name) { - selectedArrow = ; - } - return ( -
  • -
    -   {item.name} - {selectedArrow} -
    -
  • ); - }, this); - return userAndOrgsList; - } - - _makeReposList = (list) => { - var links = []; - var currentType = this.props.type; - var _this = this; - const namespace = this.state.selectedUserOrg.name; - if (currentType) { - links = list.map(function(item, idx) { - return ( -
  • - {item.name} -
  • ); - }); - } - return links; - } - - _filterRepos = (query) => { - //e.preventDefault(); - if (query) { - this.setState({ - selectedRepos: _.filter(this.state.selectedRepos, function (repo) { - return repo.name.indexOf(query) !== -1; - }) - }); - } else { - this.setState({ - selectedRepos: this.state.selectedUserOrg.repo_list - }); - } - } - - componentDidMount = () => { - //Set the first element as selected if there is none selected - if (_.isEmpty(this.state.selectedUserOrg) && this.props.repos) { - var selected = this.props.repos[0]; - this.setState({ - selectedUserOrg: selected, - selectedRepos: selected.repo_list - }); - } - } - - componentWillReceiveProps = (nextProps) => { - //Set the first element as selected if there is none selected - if (nextProps.repos && nextProps.repos.length > 0) { - var selected = nextProps.repos[0]; - this.setState({ - selectedUserOrg: selected, - selectedRepos: selected.repo_list - }); - } - } - - render() { - if (this.props.repos) { - var currentUserAndOrgs = this._makeUserOrgList(this.props.repos); - var currentRepos = []; - if (currentUserAndOrgs && currentUserAndOrgs.length > 0) { - currentRepos = this._makeReposList(this.state.selectedRepos); - } - var filterBar = (); - return ( -
    -
    -
    -
    - -
    -
    - -
    -
    -
    - ); - } else { - const slateItem = ( -
    -

    -  An error occurred while trying to connect to {this.props.type}. -

    -
    Link your account here.
    -
    - ); - return (); - } - } -} - -export default connectToStores(LinkedAccountSourcesForm, - [ - AutobuildSourceRepositoriesStore - ], - function({ getStore }, props) { - return getStore(AutobuildSourceRepositoriesStore).getState(); - }); diff --git a/app/scripts/components/repositories/RepositoryBlock.jsx b/app/scripts/components/repositories/RepositoryBlock.jsx deleted file mode 100644 index 2fabeaf3f7..0000000000 --- a/app/scripts/components/repositories/RepositoryBlock.jsx +++ /dev/null @@ -1,62 +0,0 @@ -'use strict'; - -import React, { PropTypes } from 'react'; -import { Link } from 'react-router'; - -export default React.createClass({ - displayName: 'RepositoryBlock', - propTypes: { - namespace: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - status: PropTypes.number, - description: PropTypes.string, - fullDescription: PropTypes.string, - isPrivate: PropTypes.bool, - // trusted means Automated Build - isTrusted: PropTypes.bool, - isOfficial: PropTypes.bool, - starCount: PropTypes.number, - pullCount: PropTypes.number - }, - getDefaultProps: function() { - return { - status: 0, - description: '', - fullDescription: '', - isPrivate: true, - isTrusted: false, - isOfficial: false, - starCount: 0, - pullCount: 0 - }; - }, - render: function() { - return (
  • -
    -
    -
    - -
    -
    -
    - {this.props.namespace} -
    - {this.props.name} -
    - {this.props.isPrivate ? 'Private' : 'Public'} - {this.props.isTrusted ? ' | Automated Build' : ''} -
    -
    -
    -
    -

    {this.props.description}

    -
    -
    -

    {this.props.starCount} STARS

    -

    {this.props.pullCount} DOWNLOADS

    -
    -
    -
  • - ); - } -}); diff --git a/app/scripts/components/search/ResultsNotFound.css b/app/scripts/components/search/ResultsNotFound.css deleted file mode 100644 index 0853d05e32..0000000000 --- a/app/scripts/components/search/ResultsNotFound.css +++ /dev/null @@ -1,39 +0,0 @@ -@import 'dux/css/colors.css'; - -.wrap { - height: 100%; - text-align: center; -} - -.messageModule { - animation: fadein 0.3s; - padding: 1.5rem 0 0 0; - margin: 4rem 0; -} - -@keyframes fadein { - from { - opacity: 0; - } - to { - opacity: 1; - } -} - -.heading { - color: #71859d; - font-size: 3rem; - font-weight: 400; - -} - -.subheading { - color: var(--secondary-7); -} - -.message { - color: #71859d; - margin: 0 auto; - padding: .5rem; - font-size: 1.1rem; -} diff --git a/app/scripts/components/search/ResultsNotFound.jsx b/app/scripts/components/search/ResultsNotFound.jsx deleted file mode 100644 index 7cd4a3e226..0000000000 --- a/app/scripts/components/search/ResultsNotFound.jsx +++ /dev/null @@ -1,35 +0,0 @@ -'use strict'; - -import React, { Component } from 'react'; -import styles from './ResultsNotFound.css'; - -/* - * A component similar to the RouteNotFound404Page meant for no results - * from a search or filter. Any of the props can be customized beyond text, ex: - * } /> - * to include a search icon. - */ -export default class ResultsNotFound extends Component { - - static defaultProps = { - heading: 'Sorry!', - subheading: 'We couldn\'t find any results for this search.', - message: 'Please double check your input and try again.' - } - - render() { - return ( -
    -
    -
    -
    -

    {this.props.heading}

    -

    {this.props.subheading}

    -

    {this.props.message}

    -
    -
    -
    -
    - ); - } -} diff --git a/app/scripts/components/search/Search.jsx b/app/scripts/components/search/Search.jsx deleted file mode 100644 index 5e7a77fa65..0000000000 --- a/app/scripts/components/search/Search.jsx +++ /dev/null @@ -1,149 +0,0 @@ -'use strict'; -import React, { PropTypes } from 'react'; -import FluxibleMixin from 'fluxible-addons-react/FluxibleMixin'; - -import Pagination from '../common/Pagination.jsx'; -import ResultsNotFound from './ResultsNotFound.jsx'; -import SearchStore from './../../stores/SearchStore'; -import SearchBar from './SearchBar.jsx'; -import Spinner from '../Spinner.jsx'; -import FA from '../common/FontAwesome'; -import RepositoriesList from '../common/RepositoriesList'; -import { PageHeader } from 'dux'; -import _ from 'lodash'; -import findKey from 'lodash/object/findKey'; - -var debug = require('debug')('COMPONENT:Search'); - -var _getQueryParams = function(state) { - //transition to will always have `q` appended as query param at the very least - //Other query params like: `s` -> sort by | `t=User` -> user | `t=Organization` -> Org | `f=official` - // `f=automated_builds` | `s=date_created`, `s=last_updated`, `s=alphabetical`, `s=stars`, `s=downloads` - // `s=pushes` - var queryParams = { - q: state.query || '', - page: state.page || 1, - isAutomated: state.isAutomated || 0, - isOfficial: state.isOfficial || 0, - pullCount: state.pullCount || 0, - starCount: state.starCount || 0 - }; - return queryParams; -}; - -var Search = React.createClass({ - mixins: [FluxibleMixin], - statics: { - storeListeners: [SearchStore] - }, - contextTypes: { - getStore: React.PropTypes.func.isRequired - }, - getInitialState: function() { - return this.context.getStore(SearchStore).getState(); - }, - //on Search Store Change - onChange: function() { - //When a search query has been submitted - var state = this.context.getStore(SearchStore).getState(); - this.setState(state); - }, - _getCurrentFilter: function() { - const query = this.props.location.query; - return findKey(query, (val, key) => { - return val === '1' && key !== 'q' && key !== 'page'; - }); - }, - _retransitionToSearch: function() { - this.props.history.pushState(null, '/search/', _getQueryParams(this.state)); - }, - _onFilterChange: function(event) { - event.preventDefault(); - if (event.target.value === 'isAutomated') { - this.setState({isAutomated: 1, isOfficial: 0, starCount: 0, pullCount: 0}, this._retransitionToSearch); - } else if (event.target.value === 'isOfficial') { - this.setState({isOfficial: 1, isAutomated: 0, starCount: 0, pullCount: 0}, this._retransitionToSearch); - } if (event.target.value === 'starCount') { - this.setState({starCount: 1, isOfficial: 0, isAutomated: 0, pullCount: 0}, this._retransitionToSearch); - } else if (event.target.value === 'pullCount') { - this.setState({pullCount: 1, isOfficial: 0, starCount: 0, isAutomated: 0}, this._retransitionToSearch); - } else if (event.target.value === 'all') { - this.setState({pullCount: 0, isOfficial: 0, starCount: 0, isAutomated: 0}, this._retransitionToSearch); - } - }, - _onChangePage(pageNumber) { - pageNumber = parseInt(pageNumber, 10); - this.setState({ - page: pageNumber - }, function() { - this.props.history.pushState(null, '/search/', _getQueryParams(this.state)); - }); - }, - _renderMessage() { - var message; - if (this.state.count === 0) { - if (this.state.isAutomated === '0' && this.state.isOfficial === '0') { - message = _.isEmpty(this.state.query) ? `Your search is empty!` : `Your search of '${this.state.query}' did not match any repository names or descriptions.`; - } else { - let filterType = this.state.isAutomated === '1' ? 'automated builds' : 'official repositories'; - message = `There are no ${filterType} matching '${this.state.query}'. Try removing this filter to see more results.`; - } - return ( -
    -
    - } message={ message } /> -
    -
    - ); - } else { - return ; - } - }, - _renderFilterBar() { - if (this.state.count === 0 && this.state.isAutomated === '0' && this.state.isOfficial === '0') { - return ; - } else { - return ( -
    -
    - -
    -
    - ); - } - }, - render: function() { - var maybePagination; - if (this.state.results && this.state.results.length > 0 && this.state.count > 10) { - maybePagination = ( -
    -
    - -
    -
    - ); - } - return ( -
    - -
    -
    - { this._renderFilterBar() } - - {maybePagination} -
    -
    - ); - } -}); - -module.exports = Search; diff --git a/app/scripts/components/search/SearchBar.css b/app/scripts/components/search/SearchBar.css deleted file mode 100644 index 46c8b37690..0000000000 --- a/app/scripts/components/search/SearchBar.css +++ /dev/null @@ -1,17 +0,0 @@ -@import "dux/css/box"; - -input.searchInput { - background: #405165; - border: 1px solid #4c5968; - border-radius: var(--global-radius); - color: #fff; - padding-left: 24px; -} - -.fa { - position: relative; - color: white; - max-width: 1rem; - top: -7px; - left: 6px; -} \ No newline at end of file diff --git a/app/scripts/components/search/SearchBar.jsx b/app/scripts/components/search/SearchBar.jsx deleted file mode 100644 index 86994c2df3..0000000000 --- a/app/scripts/components/search/SearchBar.jsx +++ /dev/null @@ -1,84 +0,0 @@ -'use strict'; -import React from 'react'; -import FluxibleMixin from 'fluxible-addons-react/FluxibleMixin'; -import SearchStore from '../../stores/SearchStore'; -import styles from './SearchBar.css'; -import FA from '../common/FontAwesome'; - -var debug = require('debug')('COMPONENT:SearchBar'); - -var _getQueryParams = function(state) { - //transition to will always have `q` appended as query param at the very least - //Other query params like: `s` -> sort by | `t=User` -> user | `t=Organization` -> Org | `f=official` - // `f=automated_builds` | `s=date_created`, `s=last_updated`, `s=alphabetical`, `s=stars`, `s=downloads` - // `s=pushes` - var queryParams = { - q: state.query || '', - page: state.page || 1, - isAutomated: state.isAutomated || 0, - isOfficial: state.isOfficial || 0, - starCount: state.starCount || 0, - pullCount: state.pullCount || 0 - }; - return queryParams; -}; - -var SearchBar = React.createClass({ - mixins: [FluxibleMixin], - statics: { - storeListeners: [SearchStore] - }, - contextTypes: { - getStore: React.PropTypes.func.isRequired - }, - getDefaultProps() { - return { - placeholder: 'Search' - }; - }, - getInitialState: function() { - return this.context.getStore(SearchStore).getState(); - }, - //on Search Store Change - onChange: function() { - //When a search query has been submitted - var state = this.context.getStore(SearchStore).getState(); - this.setState(state); - }, - _handleQueryChange: function(event) { - event.preventDefault(); - //Change page to number 1 when the query is changed - this.setState({ - page: 1 - }); - this.setState({query: event.target.value}); - }, - _handleQuerySubmit: function(event) { - event.preventDefault(); - //second parameter will be empty object always since we don't have /search/{?}/ - //third param will be the query /search/?q=whatever&s=blah&f=bleh - this.props.history.pushState(null, '/search/', _getQueryParams(this.state)); - }, - render: function() { - var searchQuery = this.state.query; - var inputPlaceholder = this.props.placeholder; - return ( -
    -
    -
    - -
    - -
    -
    -
    -
    - ); - } -}); - -module.exports = SearchBar; diff --git a/app/scripts/components/search/SearchResultItem.jsx b/app/scripts/components/search/SearchResultItem.jsx deleted file mode 100644 index 579c35becf..0000000000 --- a/app/scripts/components/search/SearchResultItem.jsx +++ /dev/null @@ -1,67 +0,0 @@ -'use strict'; - -import React from 'react'; -import Badge from '../Badge.jsx'; -import StatsComponent from '../StatsComponent.jsx'; -var debug = require('debug')('COMPONENT:SearchResultItem'); - -//TODO: will go under the ul in item info, will be a bunch of key value pairs reused across -//TODO: Logged out views will have the `owner/reponame` (think about this) -//TODO: Star icon should be passed to badge as d-`iconname` where `d-` is for the docker font icons - -var SearchResultItem = React.createClass({ - render: function() { - var resultItem = this.props.resultItem; - - //Push badges based on result item - var badges = []; - var officialBadge =
  • ; - var autobuildBadge =
  • ; - - // jscs:disable requireCamelCaseOrUpperCaseIdentifiers - if (resultItem.is_official) { - badges.push(officialBadge); - } else if (resultItem.is_automated) { - badges.push(autobuildBadge); - } - - //TODO: repo_owner is null atm, since API performance degrades if we try to get it - //
  • - - return ( -
  • -
    -
    -
    - -
    -
    -
    -
    {resultItem.repo_name}
    -
    -
    -
      - {badges} -
    -
    -
    -
    -
      -
    • -
    • -
    -
    -
    -
    -
    -

    {resultItem.short_description}

    -
    -
    -
    -
  • - ); - // jscs:enable - } -}); - -module.exports = SearchResultItem; diff --git a/app/scripts/components/search/SearchResults.jsx b/app/scripts/components/search/SearchResults.jsx deleted file mode 100644 index bd56981d11..0000000000 --- a/app/scripts/components/search/SearchResults.jsx +++ /dev/null @@ -1,42 +0,0 @@ -'use strict'; -/** -TODO: UNUSED COMPONENT. SHOULD REMOVE -*/ -import React from 'react'; -import ResultItem from './SearchResultItem.jsx'; -var debug = require('debug')('COMPONENT:SearchResults'); - -var SearchResults = React.createClass({ - contextTypes: { - getStore: React.PropTypes.func.isRequired - }, - getResultItem: function(resultItem, idx) { - if (resultItem.short_description) { - if (resultItem.short_description.length > 100) { - resultItem.short_description = resultItem.short_description.substring(0, 100) + '...'; - } else if (resultItem.short_description.length === 0) { - resultItem.short_description = 'No description set'; - } - } - return ; - }, - _handleSearchResultClick: function(repoName, e) { - e.preventDefault(); - //TODO: Handle official images/repos differently - this.props.history.pushState(null, `/r/${repoName}/`); - }, - render: function() { - var results = this.props.results; - var resultItems = []; - if (results) { - resultItems = results.map(this.getResultItem); - } - return ( -
    -
      {resultItems}
    -
    - ); - } -}); - -module.exports = SearchResults; diff --git a/app/scripts/components/userWrapper/UserStars.jsx b/app/scripts/components/userWrapper/UserStars.jsx deleted file mode 100644 index 1fa3055750..0000000000 --- a/app/scripts/components/userWrapper/UserStars.jsx +++ /dev/null @@ -1,67 +0,0 @@ -'use strict'; - -import React, { PropTypes, Component } from 'react'; -const { array, string, func } = PropTypes; -import connectToStores from 'fluxible-addons-react/connectToStores'; - -import UserProfileStarsStore from 'stores/UserProfileStarsStore'; -import RepositoriesList from 'common/RepositoriesList'; -import Pagination from 'common/Pagination'; -import { Module } from 'dux'; - -var debug = require('debug')('UserProfileStars'); - -var UserStars = React.createClass({ - displayName: 'UserStars', - propTypes: { - starred: array, - next: string, - prev: string - }, - _onChangePage(pageNumber) { - this.props.history.pushState(null, `/u/${this.props.user.username}/starred/`, {page: pageNumber}); - }, - render() { - - var currentPageNumber = parseInt(this.props.location.query.page, 10); - var maybePagination; - - if(this.props.starred && this.props.starred.length > 0) { - maybePagination = ( -
    -
    - -
    -
    - ); - - return ( -
    -
    - - {maybePagination} -
    -
    - ); - - } else { - - return ( - This user does not have any starred repos. - ); - - } - } -}); - -export default connectToStores(UserStars, - [ - UserProfileStarsStore - ], - function({ getStore }, props) { - return getStore(UserProfileStarsStore) - .getState(); - }); diff --git a/app/scripts/components/userprofile/Repos.jsx b/app/scripts/components/userprofile/Repos.jsx deleted file mode 100644 index 05ecd4898b..0000000000 --- a/app/scripts/components/userprofile/Repos.jsx +++ /dev/null @@ -1,79 +0,0 @@ -'use strict'; - -import React, { PropTypes, Component } from 'react'; -import { Link } from 'react-router'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import UserProfileReposStore from '../../stores/UserProfileReposStore'; -import RepositoriesList from '../common/RepositoriesList'; -import Pagination from '../common/Pagination'; -import moment from 'moment'; -import { Module } from 'dux'; - -var debug = require('debug')('UserProfileRepos'); - -class Repos extends Component { - - static propTypes = { - user: PropTypes.object.isRequired, - repos: PropTypes.array, - next: PropTypes.string, - prev: PropTypes.string - } - - _onChangePage = (pageNumber) => { - const username = this.props.params.user; - this.props.history.pushState(null, `/u/${username}/`, {page: pageNumber}); - } - - render() { - - debug(this.props); - if(this.props.repos && this.props.repos.length > 0) { - - return ( -
    -
    - - {this.renderPagination()} -
    -
    - ); - - } else { - debug(this.props); - const { username, orgname } = this.props.user; - const namespace = username || orgname; - return ( - - This user has not created any repos yet - - ); - } - } - renderPagination = (e) => { - if(this.props.repos && this.props.repos.length > 0) { - const currentPageNumber = parseInt(this.props.location.query.page, 10); - return ( -
    -
    - -
    -
    - ); - } else { - return null; - } - } -} - -export default connectToStores(Repos, - [ - UserProfileReposStore - ], - function({ getStore }, props) { - return getStore(UserProfileReposStore) - .getState(); - }); diff --git a/app/scripts/components/utils/avatar.js b/app/scripts/components/utils/avatar.js deleted file mode 100644 index 0750062fb6..0000000000 --- a/app/scripts/components/utils/avatar.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict'; - -import officialLogos from 'common/data/officialLogos.js'; -const officialImage = '/public/images/logos/mini-logo-white-inset.png'; - -const isOfficialNamespace = (namespace) => namespace === '_' || namespace === 'library'; - -// reponame is an optional param used to descriminate between official repos -// and it will be ignored unless it is an official repo -export function mkAvatarForNamespace(namespace, reponame) { - if (isOfficialNamespace(namespace) && reponame && officialLogos[reponame]) { - return `/public/images/official/${officialLogos[reponame]}`; - } - if(isOfficialNamespace(namespace) || !namespace) { - return officialImage; - } - return `${process.env.HUB_API_BASE_URL}/v2/users/${namespace}/avatar/`; -} - -/** - * This function should be treated as deprecated. We can not reliably - * detect the namespace type (User || Org) from the urls. - */ -export function mkAvatarForOrg(namespace) { - return `${process.env.HUB_API_BASE_URL}/v2/orgs/${namespace}/avatar/`; -} - -export function isOfficialAvatarURL(url) { - return url === officialImage; -} diff --git a/app/scripts/components/utils/bytesToSize.js b/app/scripts/components/utils/bytesToSize.js deleted file mode 100644 index bf0b6bebc9..0000000000 --- a/app/scripts/components/utils/bytesToSize.js +++ /dev/null @@ -1,23 +0,0 @@ -'use strict'; - -export default function bytesToSize(bytes, precision) -{ - const kilobyte = 1000; - const megabyte = kilobyte * 1000; - const gigabyte = megabyte * 1000; - const terabyte = gigabyte * 1000; - - if ((bytes >= 0) && (bytes < kilobyte)) { - return bytes + ' B'; - } else if ((bytes >= kilobyte) && (bytes < megabyte)) { - return (bytes / kilobyte).toFixed(precision) + ' KB'; - } else if ((bytes >= megabyte) && (bytes < gigabyte)) { - return (bytes / megabyte).toFixed(precision) + ' MB'; - } else if ((bytes >= gigabyte) && (bytes < terabyte)) { - return (bytes / gigabyte).toFixed(precision) + ' GB'; - } else if (bytes >= terabyte) { - return (bytes / terabyte).toFixed(precision) + ' TB'; - } else { - return 'Unknown size'; - } -} diff --git a/app/scripts/components/utils/encodeForm.js b/app/scripts/components/utils/encodeForm.js deleted file mode 100644 index 5f6b5d64d3..0000000000 --- a/app/scripts/components/utils/encodeForm.js +++ /dev/null @@ -1,17 +0,0 @@ -'use strict'; -import map from 'lodash/collection/map'; - -const _encodeForm = (obj, prefix) => { - const str = []; - map(obj, (value, key) => { - if (obj.hasOwnProperty(key)) { - const k = prefix ? `${prefix}[${key}]` : key; - str.push(typeof value === 'object' ? - _encodeForm(value, k) : - `${encodeURIComponent(k)}=${encodeURIComponent(value)}`); - } - }); - return str.join('&'); -}; - -export default _encodeForm; diff --git a/app/scripts/components/utils/validateRepositoryName.js b/app/scripts/components/utils/validateRepositoryName.js deleted file mode 100644 index 3c6167fc87..0000000000 --- a/app/scripts/components/utils/validateRepositoryName.js +++ /dev/null @@ -1,7 +0,0 @@ -'use strict'; - -export const validateRepositoryName = (name) => -{ - var repoNamePattern = /^[a-z0-9]+(?:[._-][a-z0-9]+)*$/; - return repoNamePattern.test(name); -}; diff --git a/app/scripts/components/welcome/ActivityFeedItem.jsx b/app/scripts/components/welcome/ActivityFeedItem.jsx deleted file mode 100644 index f496695aa9..0000000000 --- a/app/scripts/components/welcome/ActivityFeedItem.jsx +++ /dev/null @@ -1,41 +0,0 @@ -'use strict'; -import React from 'react'; -import moment from 'moment'; - -//TODO: remove this after a better solution is found -var _getNotificationNameForID = function(user, notificationType) { - //TODO: maybe create a link to the user's public profile page if any - if(notificationType === 'trusted_build_fail') { - return 'Automated build failure.'; - } else if (notificationType === 'new_repo_star') { - return user + ' starred a repository'; - } else if (notificationType === 'new_repo_comment') { - return user + ' added a new comment.'; - } else { - return ''; - } -}; - -var ActivityFeedItem = React.createClass({ - displayName: 'ActivityFeed', - getDefaultProps: function() { - return { - notification: 0, - /*eslint-disable camelcase */ - last_occurence: '', - /*eslint-enable camelcase */ - user: '' - }; - }, - render: function() { - return ( -
  • -
    -

    {_getNotificationNameForID(this.props.user, this.props.notification)}

    - {moment(this.props.last_occurence).fromNow()} -
    -
  • ); - } -}); - -module.exports = ActivityFeedItem; diff --git a/app/scripts/components/welcome/ChangePassSuccess.css b/app/scripts/components/welcome/ChangePassSuccess.css deleted file mode 100644 index d74134b2c6..0000000000 --- a/app/scripts/components/welcome/ChangePassSuccess.css +++ /dev/null @@ -1,9 +0,0 @@ -@import "dux/css/colors"; -@import "dux/css/box"; - -.passwordReset { - margin-top: 5rem; - border: 1px solid rgb(233, 237, 240); - border-radius: var(--global-radius); - min-height: 270px; -} diff --git a/app/scripts/components/welcome/ChangePassSuccess.jsx b/app/scripts/components/welcome/ChangePassSuccess.jsx deleted file mode 100644 index ff127d995f..0000000000 --- a/app/scripts/components/welcome/ChangePassSuccess.jsx +++ /dev/null @@ -1,30 +0,0 @@ -'use strict'; - -import React, { PropTypes } from 'react'; -import { Button } from 'dux'; -import { Link } from 'react-router'; -import ChangePasswordStore from '../../stores/ChangePasswordStore.js'; -import styles from './ChangePassSuccess.css'; - -var changePassSuccess = React.createClass({ - contextTypes: { - executeAction: PropTypes.func.isRequired - }, - PropTypes: { - changePassStore: PropTypes.shape({ - reset: PropTypes.bool.isRequired, - resetErr: PropTypes.bool.isRequired - }) - }, - render: function() { - return ( -
    -

    Your password has been reset

    -

    You may now login with your new password

    - Back to Login -
    - ); - } -}); - -module.exports = changePassSuccess; diff --git a/app/scripts/components/welcome/DashboardNewsItem.jsx b/app/scripts/components/welcome/DashboardNewsItem.jsx deleted file mode 100644 index edf3f5902f..0000000000 --- a/app/scripts/components/welcome/DashboardNewsItem.jsx +++ /dev/null @@ -1,19 +0,0 @@ -'use strict'; -const React = require('react'); - -//This is a placeholder for a news item that is shown in the dashboard. Relevant to anything that needs attention. - -var DashboardNewsItem = React.createClass({ - render: function() { - return ( -
    -
    Run Docker in your network.
    - -
    - ); - } -}); - -module.exports = DashboardNewsItem; diff --git a/app/scripts/components/welcome/DashboardTabs.jsx b/app/scripts/components/welcome/DashboardTabs.jsx deleted file mode 100644 index ed2b80b5db..0000000000 --- a/app/scripts/components/welcome/DashboardTabs.jsx +++ /dev/null @@ -1,82 +0,0 @@ -'use strict'; - -import React, { PropTypes } from 'react'; -import classnames from 'classnames'; - -/* -
    -
    -
    - NO CONTENT HERE -
    -
    -
    - */ - -export default React.createClass({ - displayName: 'DashboardTabs', - propTypes: { - myrepos: React.PropTypes.element.isRequired, - contribs: React.PropTypes.element.isRequired, - starred: React.PropTypes.element.isRequired, - activity: React.PropTypes.element.isRequired - }, - getInitialState() { - return { - tabType: 'myRepos' - }; - }, - _getActiveTab() { - switch(this.state.tabType) { - case 'myRepos': - //Show grid of my repositories - return this.props.myrepos; - case 'contrib': - //Show grid of contributed repositories - return this.props.contribs; - case 'starred': - //Show grid of my starred repositories - return this.props.starred; - case 'activity': - //Show my activity feed - return this.props.activity; - } - }, - _getTitleClassNames(type) { - return classnames({ - 'active': this.state.tabType === type, - 'tab-title': true - }); - }, - _handleTabClick(type, evt) { - evt.preventDefault(); - this.setState({ - tabType: type - }); - }, - render() { - var activeTab = this._getActiveTab(); - - return ( -
    -
    -
      -
    • My Repositories
    • -
    • Contributed
    • -
    • Starred
    • -
    • Recent Activity
    • -
    -
    -
    -
    -
    -
    - {activeTab} -
    -
    -
    -
    -
    - ); - } -}); diff --git a/app/scripts/components/welcome/ForgotPass.css b/app/scripts/components/welcome/ForgotPass.css deleted file mode 100644 index 725901d3a6..0000000000 --- a/app/scripts/components/welcome/ForgotPass.css +++ /dev/null @@ -1,42 +0,0 @@ -@import "dux/css/colors"; -@import "dux/css/box"; - -.forgotPassPage { - background: var(--docker-dark); - height: 100%; - padding-top: 100px; -} - -.forgotPassSubmit { - margin-top: var(--default-margin); - display: flex; - flex-direction: column; - justify-content: center; -} - -.header { - text-align: center; -} - -.head { - color: var(--white); - font-size: 2rem; - font-weight: 200; -} - -.subHead { - color: var(--info-color); -} - -.subHeadLight { - color: #188bb3; -} - -.logo { - width: 90px; - height: 110px; -} - -.btn { - margin-top: 1rem; -} diff --git a/app/scripts/components/welcome/ForgotPass.jsx b/app/scripts/components/welcome/ForgotPass.jsx deleted file mode 100644 index 95af29bb38..0000000000 --- a/app/scripts/components/welcome/ForgotPass.jsx +++ /dev/null @@ -1,98 +0,0 @@ -'use strict'; - -import React from 'react'; -import { Link } from 'react-router'; -import Button from '@dux/element-button'; -import FancyInput from 'common/FancyInput'; -import forgotPasswordSubmit from '../../actions/forgotPasswordSubmit.js'; -import styles from './ForgotPass.css'; -var debug = require('debug')('Password Reset'); - -module.exports = React.createClass({ - contextTypes: { - executeAction: React.PropTypes.func.isRequired - }, - getInitialState: function() { - return { - email: '', - reset: false - }; - }, - onEmailChange: function(e) { - e.preventDefault(); - this.setState({email: e.target.value}); - }, - forgotPassSubmit: function(e) { - e.preventDefault(); - debug(this.state.email); - if (this.state.email) { - this.context.executeAction(forgotPasswordSubmit, {email: this.state.email}); - this.setState({reset: true}); - } - }, - transitionHome: function(e) { - e.preventDefault(); - this.props.history.pushState(null, '/'); - }, - render: function() { - var disabledState; - if (this.state.email) { - disabledState = false; - } else { - disabledState = true; - } - - if (!this.state.reset) { - return ( -
    -
    -
    - - docker logo - -
    Reset your password
    -
    Enter an email address associated with a Docker ID.
    -
    -
    -
    -
    -
    - - -
    -
    -
    - We’ll send a password reset link to the Docker ID’s primary email address. -
    -
    - If you don't have access to your primary email address, contact Docker Support. -
    -
    - -
    -
    -
    -
    - ); - } else { - return ( -
    -
    -
    - - docker logo - -
    Reset request sent!
    -

    Password reset link sent. This link is valid for 24 hours. If you don't see a password reset link, check your spam folder.

    - -
    -
    -
    - ); - } - } -}); diff --git a/app/scripts/components/welcome/LoginForm.css b/app/scripts/components/welcome/LoginForm.css deleted file mode 100644 index a0ccde463f..0000000000 --- a/app/scripts/components/welcome/LoginForm.css +++ /dev/null @@ -1,13 +0,0 @@ -.formWrapper { - display: inline-block; - width: 100%; - margin: 1.5rem 0; -} - -.buttonWrapper { - display: flex; - justify-content: space-between; - .help { - margin: 0 .75rem; - } -} diff --git a/app/scripts/components/welcome/LoginForm.jsx b/app/scripts/components/welcome/LoginForm.jsx deleted file mode 100644 index e37ce5fa78..0000000000 --- a/app/scripts/components/welcome/LoginForm.jsx +++ /dev/null @@ -1,83 +0,0 @@ -'use strict'; - -import React, { createClass, PropTypes } from 'react'; -import _ from 'lodash'; -import { Link } from 'react-router'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import Button from '@dux/element-button'; -var debug = require('debug')('LoginForm'); - -import onChange from '../../actions/common/onChangeUtil'; -import FancyInput from 'common/FancyInput'; -import LoginStore from '../../stores/LoginStore'; -import loginUpdateFormField from '../../actions/loginUpdateFormField'; -import styles from './LoginForm.css'; - -var LoginForm = createClass({ - displayName: 'LoginForm', - contextTypes: { - executeAction: React.PropTypes.func.isRequired - }, - propTypes: { - loginAction: PropTypes.func.isRequired - }, - _onChange: onChange({ - storePrefix: 'LOGIN' - }), - _handleSubmit(event) { - event.preventDefault(); - var loginPayload = this.props.values; - loginPayload.username = loginPayload.username.toLowerCase(); - this.context.executeAction(this.props.loginAction, loginPayload); - }, - render() { - const { fields, values, variant, includeHelp } = this.props; - - var globalFormError = null; - if(this.props.globalFormError) { - globalFormError =

    {this.props.globalFormError}

    ; - } - - let loginButton = (); - if(this.props.STATUS === 'ATTEMPTING_LOGIN') { - loginButton = (); - } - let help; - if (includeHelp) { - help = ( - Can't Login? - ); - } - return ( -
    - {globalFormError} - - -
    -
    - {help} -
    - {loginButton} -
    - - ); - } -}); - -export default connectToStores(LoginForm, - [LoginStore], - function({ getStore }, props){ - return getStore(LoginStore).getState(); - }); diff --git a/app/scripts/components/welcome/ResetPass.css b/app/scripts/components/welcome/ResetPass.css deleted file mode 100644 index 4c5e3cc180..0000000000 --- a/app/scripts/components/welcome/ResetPass.css +++ /dev/null @@ -1,39 +0,0 @@ -@import "dux/css/colors"; -@import "dux/css/box"; - -.resetPassPage { - background: var(--docker-dark); - height: 100%; - padding-top: 100px; -} - -.resetPassSubmit { - margin-top: var(--default-margin); - display: flex; - flex-direction: column; - justify-content: center; -} - -.header { - text-align: center; -} - -.head { - color: var(--white); - font-size: 2rem; - font-weight: 200; -} - -.subHead { - color: var(--info-color); -} - -.logo { - width: 90px; - height: 110px; -} - -.back { - margin-top: var(--default-margin); - text-align: center; -} diff --git a/app/scripts/components/welcome/ResetPass.jsx b/app/scripts/components/welcome/ResetPass.jsx deleted file mode 100644 index 49a6ecac95..0000000000 --- a/app/scripts/components/welcome/ResetPass.jsx +++ /dev/null @@ -1,152 +0,0 @@ -/** -MjA2MTU is a base64 encoding of the pk for the user account in hub - -dhiltgen [11:07 AM] -41y-d0f275462b1678b1aeca is a random generated token - **/ -'use strict'; - -import React, { PropTypes } from 'react'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import Button from '@dux/element-button'; -import FancyInput from 'common/FancyInput'; -import { Link } from 'react-router'; -import resetPasswordSubmit from '../../actions/resetPasswordSubmit.js'; -import ChangePasswordStore from '../../stores/ChangePasswordStore.js'; -import clearChangePasswordStore from '../../actions/clearChangePasswordStore'; -import styles from './ResetPass.css'; -var debug = require('debug')('Password Reset Confirmation: '); - -var ResetPassword = React.createClass({ - contextTypes: { - executeAction: PropTypes.func.isRequired - }, - PropTypes: { - changePassStore: PropTypes.shape({ - reset: PropTypes.bool.isRequired, - resetErr: PropTypes.bool.isRequired - }) - }, - getInitialState: function() { - return { - pass1: '', - pass2: '', - passErr: false - }; - }, - onPassChange: function(e) { - e.preventDefault(); - this.setState({pass1: e.target.value}); - }, - onConfirmChange: function(e) { - e.preventDefault(); - var confirm = e.target.value; - this.setState({pass2: confirm, passErr: false}); - }, - onErrorRetry: function(e) { - e.preventDefault(); - this.setState({ - pass1: '', - pass2: '' - }); - this.context.executeAction(clearChangePasswordStore); - }, - transitionLogin: function(e) { - e.preventDefault(); - this.props.history.pushState('/login/'); - }, - resetPassSubmit: function(e) { - e.preventDefault(); - debug('reset pass submit'); - if (this.state.pass1 === this.state.pass2) { - var { uidb64, reset_token } = this.props.params; - this.context.executeAction(resetPasswordSubmit, - {uidb64: uidb64, - reset_token: reset_token, - password_1: this.state.pass1, - password_2: this.state.pass2}); - this.setState({reset: true}); - } else { - this.setState({ passErr: true }); - } - }, - render: function() { - var disabledState = (this.state.passErr || !this.state.pass1); - - if (!this.props.changePassStore.reset && !this.props.changePassStore.hasErr) { - let error; - if (this.state.passErr) { - error = 'Make sure passwords are identical'; - } - return ( -
    -
    -
    -
    Password Reset
    -
    Enter your new password.
    -
    -
    -
    -
    -
    - - - - -
    -
    -
    - ); - } else if (this.props.changePassStore.hasErr) { - return ( -
    -
    -
    -
    There was an error!
    -
    Your password has not been reset, please try again
    -
    -
    -
    -
    - -
    -
    -
    - ); - } else { - return ( -
    -
    -
    -
    Your password has been reset
    -
    You may now login with your new password
    -
    -
    -
    -
    - -
    -
    -
    - ); - } - } -}); - -module.exports = connectToStores(ResetPassword, - [ChangePasswordStore], - function({ getStore }, props) { - return { - changePassStore: getStore(ChangePasswordStore).getState() - }; - }); diff --git a/app/scripts/components/welcome/SignupForm.css b/app/scripts/components/welcome/SignupForm.css deleted file mode 100644 index 8b4531edb7..0000000000 --- a/app/scripts/components/welcome/SignupForm.css +++ /dev/null @@ -1,27 +0,0 @@ -@import "dux/css/colors"; -@import "dux/css/box"; - -.submit { - padding: var(--default-margin); - button { - float: right; - } -} - -.subtext { - /** new color variable **/ - color: #b9eafa; -} - -.heading { - font-weight: 200; - color: var(--smoke); -} - -.success { - text-align: center; - margin-top: 5rem; - .heading { - font-size: 1.5rem; - } -} diff --git a/app/scripts/components/welcome/SignupForm.jsx b/app/scripts/components/welcome/SignupForm.jsx deleted file mode 100644 index 544020c812..0000000000 --- a/app/scripts/components/welcome/SignupForm.jsx +++ /dev/null @@ -1,105 +0,0 @@ -'use strict'; - -var debug = require('debug')('SignupForm'); - -import React, { PropTypes } from 'react'; -import _ from 'lodash'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import Button from '@dux/element-button'; - -import FA from 'common/FontAwesome'; -import FancyInput from 'common/FancyInput'; -import SignupStore from '../../stores/SignupStore'; -import attemptSignup from '../../actions/attemptSignup'; -import onChange from '../../actions/common/onChangeUtil'; -import { STATUS } from '../../stores/signupstore/Constants'; -import { handleFormErrors } from './_utils'; -import styles from './SignupForm.css'; - -var SignupForm = React.createClass({ - displayName: 'SignupForm', - contextTypes: { - executeAction: PropTypes.func.isRequired - }, - PropTypes: { - location: PropTypes.object - }, - _onSubmit(e) { - e.preventDefault(); - const { partner_value, redirect_value } = this.props.location.query; - var payload = this.props.values; - payload.username = payload.username.toLowerCase(); - if (partner_value) { - payload.partner_value = partner_value; - } - if (redirect_value) { - payload.redirect_value = redirect_value; - } - debug(payload); - this.context.executeAction(attemptSignup, payload); - }, - onChange: onChange({ - storePrefix: 'SIGNUP' - }), - render() { - debug(this.props); - if(this.props.STATUS === STATUS.SUCCESSFUL_SIGNUP) { - return ( -
    -
    Sweet! You're almost ready to go!
    -

    Please check your email to activate your account.

    - -
    - ); - } else { - return ( -
    -
    -
    -

    New to Docker?

    -

    Create your free Docker ID to get started.

    -
    -
    -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    -
    - ); - } - } -}); - -export default connectToStores(SignupForm, - [SignupStore], - function({ getStore }, props) { - return getStore(SignupStore).getState(); - }); diff --git a/app/scripts/components/welcome/_utils.js b/app/scripts/components/welcome/_utils.js deleted file mode 100644 index 9ac9e62c89..0000000000 --- a/app/scripts/components/welcome/_utils.js +++ /dev/null @@ -1,43 +0,0 @@ -'use strict'; -import _ from 'lodash'; - -export function handleFormErrors(ctx, rawValueObject) { - - /** - * This function expects a ctx that has a `fields` - * object on the state, and a `_validate` function that - * returns an object `{ hasError: bool, error: string }` - * - * A valid component looks like: - * - * var Component = React.createClasse({ - * getInitialState() { - * return { - * fields: {} - * } - * }, - * _validate(key, value) { - * return { - * hasError: true, - * error: 'It\'s always wrong!' - * } - * } - * }) - */ - - // shortcut keys for State - let fields = ctx.state.fields || {}; - - // loop through `rawValueObject`, validating values - _.forIn(rawValueObject, function(value, key) { - let { hasError, error } = ctx._validate(key, value); - fields[key] = fields[key] || {}; - fields[key].hasError = hasError; - fields[key].error = error; - }, ctx); - - // queue up the new State - ctx.setState({ - fields - }); -} diff --git a/app/scripts/fluxibleRouter.js b/app/scripts/fluxibleRouter.js deleted file mode 100644 index 27194954eb..0000000000 --- a/app/scripts/fluxibleRouter.js +++ /dev/null @@ -1,112 +0,0 @@ -'use strict'; - -import React from 'react'; -import createHashHistory from 'history/lib/createHashHistory'; -import { createRoutes, useRoutes, RoutingContext } from 'react-router'; -import { routes } from 'react-router/lib/PropTypes'; -var debug = require('debug')('FluxibleRouter'); - -const { func, object } = React.PropTypes; - -/** - * A is a high-level API for automatically setting up - * a router that renders a with all the props - * it needs each time the URL changes. - */ -const FluxibleRouter = React.createClass({ - - propTypes: { - history: object, - children: routes, - routes, // alias for children - createElement: func, - onError: func, - onUpdate: func, - parseQueryString: func, - stringifyQuery: func - }, - - getInitialState() { - return { - firstRender: true, - location: null, - routes: null, - params: null, - components: null - }; - }, - - handleError(error) { - if (this.props.onError) { - this.props.onError.call(this, error); - } else { - // Throw errors by default so we don't silently swallow them! - throw error; // This error probably occurred in getChildRoutes or getComponents. - } - }, - - //============================================================================ - //ComponentWillMount is the only addition to this Router - //Needed in order to provide location/pathname to onUpdate from client.js - /* eslint-disable */ - componentWillMount() { - let { history, children, routes, parseQueryString, stringifyQuery } = this.props; - let createHistory = history ? () => history : createHashHistory; - - this.history = useRoutes(createHistory)({ - routes: createRoutes(routes || children), - parseQueryString, - stringifyQuery - }); - - this._unlisten = this.history.listen((error, state) => { - if (error) { - this.handleError(error); - } else { - //Rendering page after setting state, here to make sure the data is loaded `onUpdate` before we show the page - if (this.state.firstRender) { - this.setState({ - firstRender: false, - ...state - }); - } else { - var _this = this; - this.props.onUpdate(state, function () { - _this.setState(state); - }); - } - //End change in `onUpdate` related change to get client side rendering to behave like now - } - }); - }, - //============================================================================ - componentWillUnmount() { - if (this._unlisten) { - this._unlisten(); - } - }, - - render() { - let { location, routes, params, components } = this.state; - let { createElement } = this.props; - - if (location == null) { - return null; // Async match - } - - const routingProps = { - history: this.history, - createElement, - location, - routes, - params, - components - }; - - return ; - } - -}); -/*eslint-enable*/ - -export default FluxibleRouter; diff --git a/app/scripts/middlewares/sdk.js b/app/scripts/middlewares/sdk.js deleted file mode 100644 index 25606daf01..0000000000 --- a/app/scripts/middlewares/sdk.js +++ /dev/null @@ -1,93 +0,0 @@ -'use strict'; - -import { ATTEMPTING, ERROR, SUCCESS } from '../reduxConsts.js'; - -/** - * SDK middleware for automatically calling SDK actions and storing request - * statuses. - * - * Example: - * - * someAction({ tagName }) => ({ - * type: 'SOME_ACTION', - * meta: { - * sdk: { - * call: SDK.func, // SDK function to call - * args: ['args', 'for', 'func'] // Args to pass in to SDK function - * callback: (err, res) => ({}) // SDK callback - * statusKey: ['SOMETHING'] // Unique identifier for saving status in status reducer - * } - * } - * }) - * - * NOTE: `statusKey` should be an array; the first item should namespace - * the action type and the second item should be unique to the particular - * record. For example, when deleting a tag: - * - * statusKey: ['deleteRepoTag', 'latest'] - * - * Status will be stored in 'state.status.deleteRepoTag.latest'. - * - * NOTE: `args` does not include the SDK callback. - * - * For an example see actions/redux/tags.js - */ - -// dispatchStatus takes the action and status of an SDK request and returns -// a new action to Redux for tracking state. -// -// The 'data' parameter may be either the error or response body from the call -const dispatchStatus = (action, status, data) => ({ - type: `${action.type}_STATUS`, - payload: { - // Add in everything from the initial action payload. This lets us pass - // things such as namespaces and repo names to reducers which handle - // success states (when deleting a tag we need the namespace/repo/tag name) - ...action.payload, - statusKey: action.meta.sdk.statusKey, - status, - data - } -}); - -const sdkMiddleware = (store) => (next) => (action) => { - // If there's no meta.sdk in our action we don't need to process it with our - // middleware - if (typeof action !== 'object' || !action.meta || !action.meta.sdk) { - return next(action); - } - - const { call, args, callback, statusKey } = action.meta.sdk; - - if (!statusKey) { - throw new Error(`action.meta.sdk.statusKey is not defined for ${action.type}`); - } - - // Wrap the callback with a function that automatically dispatches error - // states for the SDK call to Redux. - // Why: this eliminates the need to create error and success dispatches for every - // action we create, and standardizes the format of all status dispatches - const wrapped = (err, res) => { - if (err) { - next(dispatchStatus(action, ERROR, err)); - // TODO: Dispatch that there was an error with this call. - } else { - next(dispatchStatus(action, SUCCESS, res)); - } - - // Ensure we call the original callback supplied for the SDK call. - if (callback) { - callback.apply(null, [err, res]); - } - }; - - // Dispatch that we're attempting the SDK call - next(dispatchStatus(action, ATTEMPTING)); - - // Make the SDK call here. - call.apply(null, [...args, wrapped]); - - return next(action); -}; - -export default sdkMiddleware; diff --git a/app/scripts/normalizers.js b/app/scripts/normalizers.js deleted file mode 100644 index 5b7ca86f53..0000000000 --- a/app/scripts/normalizers.js +++ /dev/null @@ -1,64 +0,0 @@ -'use strict'; - -import { Schema, arrayOf } from 'normalizr'; - -// Key repositories by the 'reponame' attribute instead of the 'key' field so -// that we can look up repositories by name in our reselect queries -const repository = new Schema('repository', { idAttribute: 'reponame' }); - -// The tag ID shouldn't be via key - it should be tagname -const tag = new Schema('tag', { - idAttribute: (entity) => { - // The natuilus API uses entity.tag as the tagname whereas hub uses - // entity.name - return (entity.tag) ? entity.tag : entity.name; - } -}); -// The scan ID shouldn't use the ID attribute; we need to be able to load -// any scan by checking the repo:tag combination -// TODO: Can we use the sha256sum here instead? -const scan = new Schema('scan', { - idAttribute: (entity) => `${entity.reponame}:${entity.tag}` -}); -// AKA layer -const blob = new Schema('blob', { idAttribute: 'index' }); -// Key components by names to version numbers as they have no unique ID -const component = new Schema('component', { - idAttribute: (entity) => `${entity.component}:${entity.version}` -}); -const vulnerability = new Schema('vulnerability', { idAttribute: 'cve' }); - - -// A repository has many tags -repository.define({ - tags: arrayOf(tag) -}); - -// A tag has many blobs and many scans -tag.define({ - blobs: arrayOf(blob), - // NOTE: Right now a tag can only have the latest scan. - // In the future we'll allow tags to have many scans - scans: arrayOf(scan) -}); - -scan.define({ - blobs: arrayOf(blob) -}); - -blob.define({ - components: arrayOf(component) -}); - -component.define({ - vulnerabilities: arrayOf(vulnerability) -}); - -export { - repository, - tag, - scan, - blob, - component, - vulnerability -}; diff --git a/app/scripts/records.js b/app/scripts/records.js deleted file mode 100644 index 9a603ddf48..0000000000 --- a/app/scripts/records.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; - -import { Record } from 'immutable'; - -// Records are the same as Maps but with accessors -// and can only have these defined fields set. -// USE: Instead of `shape`, in propTypes, we can use -// status: instanceOf(StatusRecord) -// -// NOTE: All records should be defined in this file -export const StatusRecord = new Record({ - status: '', - error: undefined -}); diff --git a/app/scripts/reducers/_utils.js b/app/scripts/reducers/_utils.js deleted file mode 100644 index b47be097cf..0000000000 --- a/app/scripts/reducers/_utils.js +++ /dev/null @@ -1,45 +0,0 @@ -'use strict'; - -import Immutable from 'immutable'; - -/** - * mergeEntity takes an entity name and merges it into the current state - * if found. - * - * This is used when your state contains a basic map of entities. - * - * Examples: - * - * mergeEntity('repository'): - * > merge action.payload.entities.repository into the current state - * - */ -export const mergeEntity = (entityType) => (state, action) => { - //TODO: Remove promises stuff with ready / error? - const { payload, ready, error } = action; - if (!ready || error || !payload.entities[entityType]) { - return state; - } - return state.merge(new Immutable.Map(payload.entities[entityType])); -}; - -export const mapToRecord = (map, Record) => { - let records = {}; - Object.keys(map).forEach(item => { records[item] = new Record(map[item]); }); - return records; -}; - -export const mergeEntities = (...entities) => (state, action) => { - - const { payload, ready, error } = action; - if (!ready || error) { - return state; - } - - return state.withMutations( map => { - entities.forEach( item => { - return map.mergeIn([item], new Immutable.Map(payload.entities[item])); - }); - return map; - }); -}; diff --git a/app/scripts/reducers/index.js b/app/scripts/reducers/index.js deleted file mode 100644 index fd33d66740..0000000000 --- a/app/scripts/reducers/index.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict'; - -// This combines all reducers from internal and external packages to create -// a redux store. -import { combineReducers } from 'redux'; -import repos from './repos'; -import scans from './scans'; -import status from './status'; -import tags from './tags'; -import { reducer as ui } from 'redux-ui'; - -export default combineReducers({ - // external reducers - ui, - // middleware reducers - // app-specific reducers - repos, - scans, - status, - tags -}); diff --git a/app/scripts/reducers/repos.js b/app/scripts/reducers/repos.js deleted file mode 100644 index d96a1fdcd1..0000000000 --- a/app/scripts/reducers/repos.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; - -import immutable from 'immutable'; -import { - RECEIVE_REPO -} from 'reduxConsts.js'; - -const defaultState = immutable.fromJS( - (typeof window !== 'undefined' && window.ReduxApp.repos) || {} -); - -const reducers = { - [RECEIVE_REPO]: (state, action) => { - return state.clear().merge(action.payload); - } -}; - -export default function(state = defaultState, action) { - const { type } = action; - if (typeof reducers[type] === 'function') { - return reducers[type](state, action); - } - return state; -} diff --git a/app/scripts/reducers/scans.js b/app/scripts/reducers/scans.js deleted file mode 100644 index e3074ad4e2..0000000000 --- a/app/scripts/reducers/scans.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; - -//modified from nautilus-ui/src/scripts/reducers/scans.js -import immutable from 'immutable'; -import { RECEIVE_SCANNED_TAG_DATA } from 'reduxConsts.js'; - -// Map of entities within each scan -const defaultState = immutable.fromJS( - (typeof window !== 'undefined' && window.ReduxApp.scans) || {} -); - -const reducers = { - [ RECEIVE_SCANNED_TAG_DATA ]: (state, action) => { - // Here we only ever save this current scan from the repoDetailsScannedTag - // action. This means that our scans reducer only ever has one scan - for - // the current page. - return state.clear().merge(action.payload.entities); - } -}; - -export default function(state = defaultState, action) { - if (typeof reducers[action.type] === 'function') { - return reducers[action.type](state, action); - } - return state; -} diff --git a/app/scripts/reducers/status.js b/app/scripts/reducers/status.js deleted file mode 100644 index 589187b83c..0000000000 --- a/app/scripts/reducers/status.js +++ /dev/null @@ -1,40 +0,0 @@ -'use strict'; - -import immutable, { Map } from 'immutable'; -import endsWith from 'lodash/string/endsWith'; -import isArray from 'lodash/lang/isArray'; -import { ERROR } from 'reduxConsts.js'; -import { StatusRecord } from 'records'; - -const defaultState = immutable.fromJS( - (typeof window !== 'undefined' && window.ReduxApp.status) || {} -); - -// This reducer listens for status updates from the SDK middleware -// and automatically stores the status within the `statusKey`. -// -// Example: If statusKey = ['deleteRepoTag', 'latest'] and status = 'ATTEMPTING', -// then state.status.deleteRepoTag.latest would be `ATTEMPTING`. -export default function(state = defaultState, action) { - // The status reducer only acts on actions ending in _STATUS. - // Ignore anything else and return the default state. - if (!endsWith(action.type, `_STATUS`)) { - return state; - } - - const { statusKey, status, data } = action.payload; - // We're using setIn, so if the statusKey is a string it needs - // to be wrapped in an array. - const sk = isArray(statusKey) ? statusKey : [statusKey]; - - if (status === ERROR) { - // Store the status and error response from the API within - // the state. - return state.setIn(sk, new StatusRecord({ status, error: data })); - } - - // On ATTEMPTING or SUCCESS we only want to store the status; - // storing action.payload.data would store the entire API response - // which our other reducers should be handling. - return state.setIn(sk, new StatusRecord({ status })); -} diff --git a/app/scripts/reducers/tags.js b/app/scripts/reducers/tags.js deleted file mode 100644 index cb933949cb..0000000000 --- a/app/scripts/reducers/tags.js +++ /dev/null @@ -1,91 +0,0 @@ -'use strict'; - -import immutable, { Map } from 'immutable'; -import { - RECEIVE_NAUTILUS_TAGS_FOR_REPOSITORY, - RECEIVE_TAGS_FOR_REPOSITORY, - DELETE_REPO_TAG, - SUCCESS -} from 'reduxConsts.js'; - -// Use the serialized redux data from the universal app loading if it exists. -// -// Shape of state: -// { -// 'namespace': { -// 'reponame': { -// tags: { -// 'latest': { ...data }, -// '14.04': { ...data }, -// ... -// }, -// result: [1, 2, 3, ...] // Array of repo IDs as ordered by hub API -// }, -// ... -// } -// } -// -// We use a nested map of namespace:reponame keys to a list of tags to ensure -// that we can merge the nautilus and hub API responses together without -// clearing inbetween. -const defaultState = immutable.fromJS( - (typeof window !== 'undefined' && window.ReduxApp.tags) || {} -); - -// mergeTagsIntoState accepts a namespace, reponame and normalized tag -// information and merges them into the given state. -// -// This is used when tags from the hub and nautilus API are loaded. -const mergeTagsIntoState = (state, action) => { - const { namespace, reponame, tags } = action.payload; - const path = [namespace, reponame, 'tags']; - const { tag } = tags.entities; - - return state.setIn( - path, - // Get the existing tags for this namespace/repo and merge the normalized - // tags recursively. If the namespace/repo pair doesn't exist this returns - // a new map. - // - // Merge function ensures that in the event of a conflict where the new value - // is undefined or null, it does not overwrite the existing value - state.getIn(path, new Map()).mergeDeep(tag) - ); -}; - -const maybeDeleteTag = (state, action) => { - if (action.payload.status === SUCCESS) { - // Remove this tag from our reducer. - const { namespace, reponame, tagName } = action.payload; - return state.withMutations(s => { - let result = s.getIn([namespace, reponame, 'result']); - result = result.filter(tag => tag !== tagName); - s.deleteIn([namespace, reponame, 'tags', tagName]); - s.setIn([namespace, reponame, 'result'], result); - return s; - }); - } - return state; -}; - -const reducers = { - [RECEIVE_TAGS_FOR_REPOSITORY]: (state, action) => { - // Add the result array of ordered tags from the hub API response, - // then merge tags in - const { namespace, reponame, tags } = action.payload; - const path = [namespace, reponame, 'result']; - const { result } = tags; - state = state.setIn(path, result); - return mergeTagsIntoState(state, action); - }, - [RECEIVE_NAUTILUS_TAGS_FOR_REPOSITORY]: mergeTagsIntoState, - [`${DELETE_REPO_TAG}_STATUS`]: maybeDeleteTag -}; - -export default function(state = defaultState, action) { - const { type } = action; - if (typeof reducers[type] === 'function') { - return reducers[type](state, action); - } - return state; -} diff --git a/app/scripts/reduxConsts.js b/app/scripts/reduxConsts.js deleted file mode 100644 index 6ee2ee93b4..0000000000 --- a/app/scripts/reduxConsts.js +++ /dev/null @@ -1,19 +0,0 @@ -'use strict'; -//Consts used for redux actions -const keyMirror = require('keymirror'); - -export default keyMirror({ - //repos - RECEIVE_REPO: null, - - //tags - DELETE_REPO_TAG: null, - RECEIVE_NAUTILUS_TAGS_FOR_REPOSITORY: null, - RECEIVE_SCANNED_TAG_DATA: null, - RECEIVE_TAGS_FOR_REPOSITORY: null, - - // statuses - ATTEMPTING: null, - ERROR: null, - SUCCESS: null -}); diff --git a/app/scripts/reduxStore.js b/app/scripts/reduxStore.js deleted file mode 100644 index a5aaf0748f..0000000000 --- a/app/scripts/reduxStore.js +++ /dev/null @@ -1,38 +0,0 @@ -'use strict'; - -// This creates a new redux store by importing our reducers and middleware -// and combining the two. -import { applyMiddleware, compose, createStore } from 'redux'; -import { Iterable } from 'immutable'; -import reducers from './reducers'; -import sdkMiddleware from './middlewares/sdk.js'; -import createLogger from 'redux-logger'; -const debug = require('debug')('hub:redux:logger'); - - -// Logger must always be the last middleware in applyMiddleware -const logger = createLogger({ - predicate: () => process.env.ENV === `development`, - // Use the debug import as our logger - logger: {log: debug}, - // Transform any immutableJS maps and iterables into their standard JS - // counterparts. This means you can inspect state within the console. - stateTransformer: (state) => { - let newState = {}; - Object.keys(state).forEach(key => { - newState[key] = state[key]; - if (Iterable.isIterable(state[key])) { - newState[key] = state[key].toJS(); - } - }); - return newState; - } -}); - -// Compose creates a new function by taking store enhancers (such as middleware -// and any external enhancers) which modifies the createStore function. -const enhancedCreateStore = compose( - applyMiddleware(sdkMiddleware, logger) -)(createStore); - -export default enhancedCreateStore; diff --git a/app/scripts/reduxUtils.js b/app/scripts/reduxUtils.js deleted file mode 100644 index dfba193f92..0000000000 --- a/app/scripts/reduxUtils.js +++ /dev/null @@ -1,27 +0,0 @@ -'use strict'; - -import { bindActionCreators } from 'redux'; -import React from 'react'; -import consts from './reduxConsts'; -/** - * Given an object of actions, this returns a thunk which returns all actions - * bound to dispatch using the same key names. - * - * This allows us to use `this.props.actions.$actionName` within components - * after being connected to Redux. - * - * Example: - * - * @connect(mapState, mapActions(Actions)) - * class Basic extends Component { - * // this.props.actions now containers all keys in Actions bound to dispatch - * } - * - */ -export let mapActions = (actions) => { - return (dispatch) => { return { actions: bindActionCreators(actions, dispatch) }; }; -}; - -export const mapToArray = (map) => { - return Object.keys(map).map(key => map[key]); -}; diff --git a/app/scripts/selectors/status.js b/app/scripts/selectors/status.js deleted file mode 100644 index 92b5d05e21..0000000000 --- a/app/scripts/selectors/status.js +++ /dev/null @@ -1,3 +0,0 @@ -'use strict'; - -export const getStatus = (state) => state.status; diff --git a/app/scripts/server.js b/app/scripts/server.js deleted file mode 100644 index edae4a4263..0000000000 --- a/app/scripts/server.js +++ /dev/null @@ -1,342 +0,0 @@ -'use strict'; -var debug = require('debug')('hub:server'); -var path = require('path'); -if(process.env.NEW_RELIC_LICENSE_KEY && process.env.NEW_RELIC_APP_NAME) { - process.env.NEW_RELIC_NO_CONFIG_FILE = true; - require('newrelic'); -} -var request = require('superagent'); -var bugsnag = require('bugsnag'); - -import pick from 'lodash/object/pick'; -import merge from 'lodash/object/merge'; -import React from 'react'; -import { match } from 'react-router'; -import RoutingContext from 'react-router/lib/RoutingContext'; -import bootstrapCreateElement from './bootstrapCreateElement'; -import app from './app'; -import cookieParser from 'cookie-parser'; -import bodyParser from 'body-parser'; -import express from 'express'; -import favicon from 'serve-favicon'; -import navigateAction from './actions/navigate'; -import serialize from 'serialize-javascript'; -import HtmlComponent from './components/Html'; - -import { Provider } from 'react-redux'; -import reducers from './reducers'; -import enhancedCreateStore from './reduxStore'; - -const server = express(); - -// don't broadcast we are using express -server.disable('x-powered-by'); - -// add bugsnag for asynch errors -if (process.env.BUGSNAG_API_KEY) { - bugsnag.register(process.env.BUGSNAG_API_KEY); - server.use(bugsnag.requestHandler); -} - -server.use(favicon('./favicon.ico')); -server.use('/public', express.static('./public')); - -// Add a trailing '/' to the path if there is none -server.use(function(req, res, next) { - if (req.path.substr(-1) !== '/' && req.path.length > 1) { - const query = req.url.slice(req.path.length); - res.redirect(301, req.path + '/' + query); - } else { - next(); - } -}); - -// standard health check endpoint -server.get('/_health', function (req, res) { - res.send('OK'); -}); - -(function(){ - const redirectToDockerPricing = function(req, res) { - res.redirect(301, 'https://www.docker.com/pricing'); - }; - - const redirectTrialToDockerStore = function(req, res) { - res.redirect(301, 'https://store.docker.com/bundles/docker-datacenter/purchase?plan=free-trial'); - }; - - server.get('/enterprise/trial/', redirectTrialToDockerStore); // redirect DDC Trial page to new Store page - server.get('/enterprise/', redirectToDockerPricing); - server.get('/subscriptions/', redirectToDockerPricing); -})(); - -server.get('/account/signup/', function(req, res, next) { - res.redirect('/'); -}); - -server.get('/account/forgot-password/', function(req, res, next) { - res.redirect('/reset-password/'); -}); - -server.get('/account/login/', function(req, res, next) { - res.redirect('/login/'); -}); - -server.get('/_/', function(req, res, next) { - res.redirect('/explore/'); -}); - -server.get('/official/', function(req, res, next) { - res.redirect('/explore/'); -}); - -server.get('/account/accounts/', function(req, res, next) { - res.redirect('/account/authorized-services/'); -}); - -server.get('/plans/', function(req, res, next) { - res.redirect('https://www.docker.com/pricing'); -}); - -server.get('/resend-email-confirmation/', function(req, res, next) { - res.redirect('/reset-password/'); -}); - -//There are two cases now: -//Case 1: No query parameter, just the token | Default activation, with confirmation_key sent to the `activate` endpoint -//Case 2: A `ref` query parameter is sent in the email validation URL | For partners, we send both key and ref to the activation endpoint -server.get('/account/confirm-email/:token', function(req, res, next) { - if(req.params.token) { - //If on activate, we get a query parameter called `ref` back from the email link, we store it and send it with the POST - const { ref } = req.query; - const { token } = req.params; - var activateRequestBody = { confirmation_key: token }; - if (ref) { - activateRequestBody.ref = ref; - } - request.post(`${process.env.REGISTRY_API_BASE_URL}/v2/users/activate/`) - .accept('application/json') - .send(activateRequestBody) - .end((err, apiRes) => { - if (err) { - debug('sign up error', err); - //Redirect to Login page for any error. - //We do not have generic error pages for 400s or 500s. - res.redirect('/login/'); - } else if (!apiRes || !apiRes.body) { - debug('api response is empty'); - //Redirect to Login page, when there is no response - //This is a care case that needs to be handled to make sure - //that it doesn't crash. See HUB-2094 for further details. - res.redirect('/login/'); - } else { - const { redirect_url } = apiRes.body; - if (redirect_url) { - //Redirect to the redirect URL returned by the API - res.redirect(redirect_url); - } else { - //Fallback redirect to Login page, when there is no redirect URL - res.redirect('/login/'); - } - } - }); - } else { - res.redirect('/login/'); - } -}); - -server.use(cookieParser()); -// 30 days in ms: 2592000000 -const expiry = 1000 * 60 * 60 * 24 * 30; // ms * s * m * h * days -const cookieOpts = { - domain: process.env.COOKIE_DOMAIN, - httpOnly: true, - secure: true, - maxAge: expiry, - expires: new Date(Date.now() + expiry) -}; -server.post('/attempt-login/', - bodyParser.json(), - function(req, res, next) { - res.cookie('token', req.body.jwt, cookieOpts); - res.end(); -}); - -const isLoggedIn = function(req) { - return !!(req.cookies && (req.cookies.token || req.cookies.jwt)); -}; - -server.get('/account/billing-plans/', function(req, res, next) { - if (!isLoggedIn(req)) { - return res.redirect('/billing-plans/'); - } - next(); -}); - -server.use(function(req, res, next) { - if (req.method !== 'GET') { - return next(); - } - if (isLoggedIn(req) && (['/login/', '/reset-password/', '/register/'].indexOf(req.path) !== -1 || req.path.indexOf('/account/password-reset-confirm') === 0)) { - res.redirect('/'); - } else if (!isLoggedIn(req) && req.path.indexOf('password-reset-confirm') === -1 && req.path.indexOf('/account/') === 0) { - res.redirect('/login/'); - } else { - next(); - } -}); - -server.post('/attempt-logout/', function(req, res, next) { - /** - * Delete the old cookie when we see it on logout. - */ - const oldCookieOpts = merge({}, - cookieOpts, - { - domain: '.docker.com' - }); - res.clearCookie('jwt', oldCookieOpts); - res.clearCookie('token', cookieOpts); - res.end(); -}); - -server.post('/oauth/github-attempt/', - bodyParser.json(), - function(req, res, next) { - res.cookie('ghOauthKey', req.body.ghk, cookieOpts); - res.end(); -}); - -server.post('/oauth/github-done/', function(req, res, next) { - res.clearCookie('ghOauthKey', cookieOpts); - res.end(); -}); - -server.use(function(req, res, next) { - // We may need to whitelist OPTIONS - if (req.method !== 'GET') { - res.end('This server does not respond to non-GET requests'); - } else { - next(); - } -}); - -server.use(function(req, res, next) { - // Within each request create a new Redux store from all of our reducers - // so that state is unique per request. - const store = enhancedCreateStore(reducers); - const context = app.createContext({ - reduxStore: store - }); - - debug('context:', context, context.reduxStore); - - //We get the Routes that have been created in the FluxibleComponent - const routes = app.getComponent(); - - const originalURL = req.originalUrl; - //We use the 'match' API to match the created routes with the current location (req.originalURL) - debug('matching route', originalURL); - match({ routes, location: originalURL }, (routerError, redirectLocation, renderProps) => { - // match uses createRoutes for history - //TODO: handle redirect, not found and errors - //TODO: need to handle generic 404s, 500s, 301s - //if (redirectLocation) { - //TODO: redirects need to be handled here - // res.redirect(301, redirectLocation.pathname + redirectLocation.search); - //} - //else if (error) { - //TODO: Render a nice 500 page with error displayed | HOPE THIS NEVER HAPPENS - // res.send(500, error.message); - //} - //else if (renderProps == null) { - //TODO: Probably render the 404 page here - // res.send(404, 'Not found'); - //} - - //If router errors out, bail - if (routerError) { - debug('Error in the Router', routerError); - res.end(routerError); - } - // whitelist cookies from express into renderProps - if (req.cookies) { - renderProps.cookies = pick(req.cookies, ['token', 'ghOauthKey']); - // For backward compat since we changed the cookie name - renderProps.cookies.jwt = renderProps.cookies.token; - } - - // Set the props, so the server knows if the user is logged in - if (renderProps.cookies.jwt) { - renderProps.JWT = renderProps.cookies.jwt; - } - - /** - * Execute navigate action to load data (we block the render until the data is - * completely loaded) - * You can see the actual server side render happens only after the - * `navigateAction` calls `done()` somewhere - */ - context.executeAction(navigateAction, renderProps, function() { - debug('Exposing context state', context); - debug('EXPOSING RENDER PROPS', renderProps); - let serializedApp; - let reduxApp; - try { - /* - NOTE: If we have any html or request responses saved in the store - - serialize will not be able to parse this and will crash the node server - */ - serializedApp = serialize(app.dehydrate(context)); - reduxApp = serialize(store.getState()); - } catch (err) { - debug('SERIALIZATION FAILURE: ', err); - } - const exposed = `window.App=${serializedApp}; window.ReduxApp = ${reduxApp};`; - debug('Rendering Application component into html'); - - // This is the Router 1.0.0 recommended way of doing server side rendering - // Also add a Provider around the routingContext for Redux. - // NOTE: We're defining our redux store above directly within the app context - const routingContext = ( - - - - ); - - debug('rendering html'); - var html = React.renderToStaticMarkup( - - ); - - res.send(html); - }); - }); -}); - -// add bugsnag for error handling middleware -if(process.env.BUGSNAG_API_KEY) { - server.use(bugsnag.errorHandler); -} - -// add generic error catching middleware so the server doesn't crash -server.use(function catchError(err, req, res, next) { - const message = err.stack ? err.stack.replace(/\n/g, '') : ''; - const errorLog = { - time: (new Date()).toISOString(), - service: 'hub-web-v2', - message - }; - console.error(errorLog); // eslint-disable-line no-console -}); - -const port = process.env.PORT || 3000; - -// Stop the server if the process terminates -const runningServer = server.listen(port, function onListen() { - process.on('exit', runningServer.close.bind(runningServer)); - debug('Listening on port ' + port); -}); diff --git a/app/scripts/stores/AccountInfoFormStore.js b/app/scripts/stores/AccountInfoFormStore.js deleted file mode 100644 index 0102a883c1..0000000000 --- a/app/scripts/stores/AccountInfoFormStore.js +++ /dev/null @@ -1,131 +0,0 @@ -'use strict'; - -var createStore = require('fluxible/addons/createStore'); -import { STATUS } from './common/Constants'; -var debug = require('debug')('AccountInfoFormStore'); -var _ = require('lodash'); - -var noErrorObj = { - hasError: false, - error: '' -}; - -export default createStore({ - storeName: 'AccountInfoFormStore', - handlers: { - ACCOUNT_INFO_CLEAR_FORM: '_clearForm', - ACCOUNT_INFO_UPDATE_FIELD_WITH_VALUE: '_updateFieldWithValue', - ACCOUNT_INFO_ATTEMPT_START: '_attemptStart', - ACCOUNT_INFO_BAD_REQUEST: '_badRequest', - ACCOUNT_INFO_SUCCESS: '_success', - ACCOUNT_INFO_STATUS_CLEAR: '_clearStatus', - ACCOUNT_INFO_FACEPALM: '_facepalm', - RECEIVE_USER: '_receiveUser' - }, - initialize() { - this.STATUS = STATUS.DEFAULT; - - this.fields = { - full_name: {}, - company: {}, - location: {}, - profile_url: {}, - gravatar_email: {} - }; - - this.values = { - full_name: '', - company: '', - location: '', - profile_url: '', - gravatar_email: '' - }; - }, - _receiveUser(user) { - debug('receive user', user); - this.values.full_name = user.full_name; - this.values.company = user.company; - this.values.location = user.location; - this.values.profile_url = user.profile_url; - this.values.gravatar_email = user.gravatar_email; - this.emitChange(); - }, - _facepalm() { - // this happens if things are screwed and we can't recover gracefully - this.STATUS = STATUS.FACEPALM; - this.emitChange(); - }, - _clearForm() { - this.initialize(); - this.emitChange(); - }, - _updateFieldWithValue({fieldKey, fieldValue}) { - this.STATUS = STATUS.DEFAULT; - this.values[fieldKey] = fieldValue; - this.emitChange(); - }, - _attemptStart() { - this.STATUS = STATUS.ATTEMPTING; - this.fields = { - full_name: {}, - company: {}, - location: {}, - profile_url: {}, - gravatar_email: {} - }; - this.emitChange(); - }, - _success() { - this.STATUS = STATUS.SUCCESSFUL; - this.emitChange(); - }, - _clearStatus() { - this.STATUS = STATUS.DEFAULT; - this.emitChange(); - }, - _badRequest(obj) { - /** - * This function expects keys which match the `this.fields` keys - * with an array of errors: - * - * { - * orgname: ['this field is required'] - * } - */ - let shouldEmitChange = false; - this.STATUS = STATUS.ERROR; - - // cycle through the possible form fields - this.fields = _.mapValues(this.fields, function (errorObject, key) { - if(_.has(obj, key)) { - shouldEmitChange = true; - return { - hasError: !!obj[key], - error: obj[key][0] - }; - } else { - return errorObject; - } - }); - - if(shouldEmitChange) { - this.emitChange(); - } - }, - getState() { - return { - fields: this.fields, - values: this.values, - STATUS: this.STATUS - }; - }, - dehydrate() { - return this.getState(); - }, - rehydrate(state) { - debug('rehydrate', state); - this.fields = state.fields; - this.values = state.values; - this.STATUS = state.STATUS; - } -}); diff --git a/app/scripts/stores/AccountSettingsLicensesStore.js b/app/scripts/stores/AccountSettingsLicensesStore.js deleted file mode 100644 index 40274dddb7..0000000000 --- a/app/scripts/stores/AccountSettingsLicensesStore.js +++ /dev/null @@ -1,41 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -var debug = require('debug')('AccountSettingsLicenseStore'); -import _ from 'lodash'; - -export default createStore({ - storeName: 'AccountSettingsLicensesStore', - handlers: { - RECEIVE_LICENSES: '_receiveLicenses' - }, - initialize: function() { - this.licenses = []; - this.attempting = true; - }, - _receiveLicenses: function(licenses) { - this.licenses = _.flatten(licenses); - this.attempting = false; - this.emitChange(); - }, - getAttempt: function() { - return this.attempting; - }, - setAttempt: function(flag) { - this.attempting = flag; - }, - getState: function() { - return { - licenses: this.licenses, - attempting: this.attempting - }; - }, - rehydrate: function(state) { - this.licenses = state.licenses; - this.attempting = state.attempting; - }, - dehydrate: function() { - return this.getState(); - } -}); - diff --git a/app/scripts/stores/AccountSettingsTeamsStore.js b/app/scripts/stores/AccountSettingsTeamsStore.js deleted file mode 100644 index 17b7d9a462..0000000000 --- a/app/scripts/stores/AccountSettingsTeamsStore.js +++ /dev/null @@ -1,29 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; - -export default createStore({ - storeName: 'AccountSettingsTeamsStore', - handlers: { - RECEIVE_LICENSES: '_receiveLicenses' - }, - initialize() { - this.licenses = []; - }, - _receiveLicenses(res) { - this.licenses = res.results; - this.emitChange(); - }, - getState() { - return { - licenses: this.licenses - }; - }, - rehydrate(state) { - this.licenses = state.licenses; - }, - dehydrate() { - return this.getState(); - } -}); - diff --git a/app/scripts/stores/AddOrganizationStore.js b/app/scripts/stores/AddOrganizationStore.js deleted file mode 100644 index 7fd9986b2d..0000000000 --- a/app/scripts/stores/AddOrganizationStore.js +++ /dev/null @@ -1,115 +0,0 @@ -'use strict'; - -var createStore = require('fluxible/addons/createStore'); -import { STATUS } from './addorganizationstore/Constants'; -var debug = require('debug')('AddOrganizationStore'); -var _ = require('lodash'); - -var noErrorObj = { - hasError: false, - error: '' -}; - -export default createStore({ - storeName: 'AddOrganizationStore', - handlers: { - ADD_ORG_CLEAR_FORM: '_clearForm', - ADD_ORG_UPDATE_FIELD_WITH_VALUE: '_updateFieldWithValue', - ADD_ORG_ATTEMPT_START: '_addOrgAttemptStart', - ADD_ORG_BAD_REQUEST: '_badRequest', - ADD_ORG_SUCCESS: '_addOrgSuccess', - ADD_ORG_FACEPALM: '_facepalm', - CREATED_ORGANIZATION: '_clearForm', - CLEAR_ERRORS: '_clearErrors' - }, - initialize() { - this.STATUS = STATUS.DEFAULT; - - this.fields = { - gravatar_email: {}, - orgname: {}, - location: {}, - company: {}, - profile_url: {} - }; - - this.values = { - gravatar_email: '', - orgname: '', - location: '', - company: '', - profile_url: '' - }; - }, - _facepalm() { - // this happens if things are screwed and we can't recover gracefully - this.STATUS = STATUS.FACEPALM; - this.emitChange(); - }, - _clearForm() { - this.initialize(); - this.emitChange(); - }, - _updateFieldWithValue({fieldKey, fieldValue}) { - this._clearErrors(fieldKey); - this.values[fieldKey] = fieldValue; - this.emitChange(); - }, - _attemptStart() { - this.STATUS = STATUS.ATTEMPTING; - this.emitChange(); - }, - _signupSuccess() { - this.STATUS = STATUS.SUCCESSFUL_SIGNUP; - this.emitChange(); - }, - _clearErrors(fieldKey) { - if (this.STATUS === STATUS.BAD_REQUEST || this.STATUS === STATUS.FACEPALM) { - this.fields[fieldKey] = noErrorObj; - this.STATUS = STATUS.DEFAULT; - this.emitChange(); - } - }, - _badRequest(obj) { - /** - * This function expects keys which match the `this.fields` keys - * with an array of errors: - * - * { - * orgname: ['this field is required'] - * } - */ - let shouldEmitChange = false; - this.STATUS = STATUS.BAD_REQUEST; - - // cycle through the possible form fields - this.fields = _.mapValues(this.fields, function (errorObject, key) { - if(_.has(obj, key)) { - shouldEmitChange = true; - return { - hasError: !!obj[key], - error: obj[key][0] - }; - } else { - return errorObject; - } - }); - - if(shouldEmitChange) { - this.emitChange(); - } - }, - getState() { - return { - fields: this.fields, - values: this.values, - STATUS: this.STATUS - }; - }, - dehydrate() { - return {}; - }, - rehydrate(state) { - this.state = state; - } -}); diff --git a/app/scripts/stores/AddTrialLicenseStore.js b/app/scripts/stores/AddTrialLicenseStore.js deleted file mode 100644 index d448f26f50..0000000000 --- a/app/scripts/stores/AddTrialLicenseStore.js +++ /dev/null @@ -1,64 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -import { ATTEMPTING_DOWNLOAD, - BAD_REQUEST, - DEFAULT, - FACEPALM, - SUCCESSFUL_DOWNLOAD } from 'stores/addtriallicensestore/Constants'; -const debug = require('debug')('AddTrialLicenseStore'); - -export default createStore({ - storeName: 'AddTrialLicenseStore', - handlers: { - ATTEMPTING_LICENSE_DOWNLOAD_START: '_attemptingLicenseDownloadStart', - DOWNLOAD_LICENSE_CONTENT_BAD_REQUEST: '_downloadLicenseContentBadRequest', - DOWNLOAD_LICENSE_CONTENT_FACEPALM: '_facepalm', - RECEIVE_LICENSE_DOWNLOAD_CONTENT: '_receiveLicenseDownloadContent' - }, - initialize: function() { - this.error = ''; - this.STATUS = DEFAULT; - }, - _attemptingLicenseDownloadStart: function() { - this.STATUS = ATTEMPTING_DOWNLOAD; - this.error = ''; - this.emitChange(); - }, - _clearFeedbackStates: function() { - this.STATUS = DEFAULT; - this.error = ''; - this.emitChange(); - }, - _downloadLicenseContentBadRequest: function(err) { - this.STATUS = BAD_REQUEST; - this.error = err; - this.emitChange(); - }, - _facepalm: function(err) { - this.STATUS = FACEPALM; - debug(err); - this.error = 'Sorry, an error occured and your license is unavailable at this time.'; - this.emitChange(); - }, - _receiveLicenseDownloadContent: function() { - this.STATUS = SUCCESSFUL_DOWNLOAD; - this.error = ''; - setTimeout(this._clearFeedbackStates.bind(this), 5000); - this.emitChange(); - }, - getState: function() { - return { - error: this.error, - STATUS: this.STATUS - }; - }, - rehydrate: function(state) { - this.error = state.error; - this.STATUS = state.STATUS; - }, - dehydrate: function() { - return this.getState(); - } -}); - diff --git a/app/scripts/stores/AddWebhookFormStore.js b/app/scripts/stores/AddWebhookFormStore.js deleted file mode 100644 index e315647c2f..0000000000 --- a/app/scripts/stores/AddWebhookFormStore.js +++ /dev/null @@ -1,86 +0,0 @@ -'use strict'; -import createStore from 'fluxible/addons/createStore'; -import last from 'lodash/array/last'; -import { - DEFAULT, - ATTEMPTING, - ERROR -} from './addwebhookformstore/Constants'; -const debug = require('debug')('AddWebhookFormStore'); - -var WebhooksSettingsStore = createStore({ - storeName: 'AddWebhookFormStore', - handlers: { - RECEIVE_WEBHOOKS: '_receiveWebhooks', - ADD_WEBHOOK_CLEAR: '_clear', - ADD_WEBHOOK_START: '_start', - ADD_WEBHOOK_RESET: '_reset', - ADD_WEBHOOK_SUCCESS: '_success', - ADD_WEBHOOK_NEW_HOOK: '_newHook', - ADD_WEBHOOK_REMOVE_HOOK: '_removeHook', - ADD_WEBHOOK_ERROR: '_error', - ADD_WEBHOOK_MISSING_ARGS: '_handleMissingArgs', - ADD_WEBHOOK_VALIDATION_ERRORS: '_handleValidationErrors' - }, - initialize() { - /** - * hookFields represent each `input` pairing that is - * rendered. They contain no data about the content of the input - */ - this.hookFields = [1]; - this.STATUS = DEFAULT; - this.serverErrors = {}; - }, - _error(args) { - // TODO: handle generic error - this.STATUS = ERROR; - this.serverErrors = args; - this.emitChange(); - }, - _handleMissingArgs(args) { - debug('missing args: ', args); - this.serverErrors = args; - }, - _handleValidationErrors(args) { - debug('validation errors: ', args); - this.serverErrors = args; - }, - _newHook() { - const { hookFields: fields } = this; - this.hookFields = fields.concat(last(fields) + 1); - this.emitChange(); - }, - _reset() { - this.initialize(); - this.emitChange(); - }, - _start() { - this.STATUS = ATTEMPTING; - this.emitChange(); - }, - _success() {}, - _receiveWebhooks(payload) { - debug(payload); - this.pipelines = payload.results; - this.emitChange(); - }, - _receiveAddWebhookErrors(error) { - }, - getState() { - return { - STATUS: this.STATUS, - pipelines: this.pipelines, - hookFields: this.hookFields, - serverErrors: this.serverErrors - }; - }, - dehydrate() { - return this.getState(); - }, - rehydrate(state) { - this.pipelines = state.pipelines; - this.hookFields = state.hookFields; - } -}); - -module.exports = WebhooksSettingsStore; diff --git a/app/scripts/stores/ApplicationStore.js b/app/scripts/stores/ApplicationStore.js deleted file mode 100644 index 6b4ea63eb6..0000000000 --- a/app/scripts/stores/ApplicationStore.js +++ /dev/null @@ -1,33 +0,0 @@ -'use strict'; -const createStore = require('fluxible/addons/createStore'); - -var ApplicationStore = createStore({ - storeName: 'ApplicationStore', - handlers: { - CHANGE_ROUTE: 'handleNavigate' - }, - initialize: function() { - this.currentRoute = null; - }, - handleNavigate: function(route) { - if (this.currentRoute && route.path === this.currentRoute.path) { - return; - } - - this.currentRoute = route; - this.emitChange(); - }, - getState: function() { - return { - route: this.currentRoute - }; - }, - dehydrate: function() { - return this.getState(); - }, - rehydrate: function(state) { - this.currentRoute = state.route; - } -}); - -module.exports = ApplicationStore; diff --git a/app/scripts/stores/AutoBuildSettingsStore.js b/app/scripts/stores/AutoBuildSettingsStore.js deleted file mode 100644 index 117c3c63e1..0000000000 --- a/app/scripts/stores/AutoBuildSettingsStore.js +++ /dev/null @@ -1,235 +0,0 @@ -'use strict'; -import createStore from 'fluxible/addons/createStore'; -import sortBy from 'lodash/collection/sortBy'; -import { STATUS } from './common/Constants'; - -var AutoBuildSettingsStore = createStore({ - storeName: 'AutoBuildSettingsStore', - handlers: { - AB_TRIGGER_BY_TAG_ERROR: '_triggerByTagError', - AB_TRIGGER_BY_TAG_SUCCESS: '_triggerByTagSuccess', - ATTEMPT_TRIGGER_BY_TAG: '_triggerByTagAttempt', - RECEIVE_AUTOBUILD_SETTINGS: '_receiveAutoBuildSettings', - UPDATE_AUTO_BUILD_SETTINGS: '_updateFields', - RECEIVE_AUTOBUILD_LINKS: '_receiveAutoBuildLinks', - LINK_AUTOBUILD_ERROR: '_linkAutoBuildError', - LINK_AUTOBUILD_SUCCESS: '_linkAutoBuildSuccess', - UPDATE_AUTOBUILD_PUSH_TRIGGER_ITEM: '_updateBuildTriggerItem', - UPDATE_AUTOBUILD_NEW_TAG_ITEM: '_updateBuildNewTagItem', - DELETE_AUTOBUILD_PUSH_TRIGGER_ITEM: '_deleteBuildTriggerItem', - DELETE_AUTOBUILD_NEW_TAG_ITEM: '_deleteBuildsNewTagItem', - ADD_AUTOBUILD_PUSH_TRIGGER_ITEM: '_addBuildTriggerItem', - SAVE_BUILD_TAGS_SUCCESS: '_saveTagsSuccess', - SAVE_BUILD_TAGS_ERROR: '_saveTagsError', - RECEIVE_TRIGGER_STATUS: '_receiveTriggerStatus', - RECEIVE_TRIGGER_LOGS: '_receiveTriggerLogs' - }, - initialize: function() { - this.autoBuildStore = { - repository: '', - build_name: '', - provider: '', - source_url: '', - docker_url: '', - repo_web_url: '', - repo_type: '', - active: false, - deleted: false, - repo_id: '', - build_tags: [], - deploykey: null, - hook_id: '' - }; - this.newTags = []; - this.validations = { - buildTags: { - hasError: false, - success: false, - errors: [] - }, - links: { - hasError: false, - success: false, - error: '' - }, - trigger: { - success: '', - error: '' - } - }; - this.autoBuildBlankSlate = {}; - this.autoBuildLinks = []; - this.triggerLinkForm = { - repoName: '' - }; - this.triggerStatus = { - token: '', - trigger_url: '', - active: false - }; - this.triggerLogs = []; - this.STATUS = STATUS.DEFAULT; - }, - _resetValidations: function(field) { - if (field === 'buildTags') { - this.validations.buildTags = { - hasError: false, - success: false, - errors: [] - }; - } else { - this.validations[field] = { - hasError: false, - success: false, - error: '' - }; - } - this.emitChange(); - }, - _receiveAutoBuildSettings: function(payload) { - this.autoBuildStore = payload; - const sorted = sortBy(payload.build_tags, 'id'); // ensure build_tags received are sorted - this.autoBuildStore.build_tags = sorted; - this.autoBuildBlankSlate = this.autoBuildStore; - this.emitChange(); - }, - _receiveAutoBuildLinks: function(payload) { - this.autoBuildLinks = payload; - this.triggerLinkForm.repoName = ''; - this.emitChange(); - }, - _linkAutoBuildError: function() { - this.validations.links = { - hasError: true, - success: false, - error: 'Failed to link this repository to your Automated Build.' - }; - this.emitChange(); - }, - _linkAutoBuildSuccess: function() { - this.validations.links = { - hasError: false, - success: true, - error: '' - }; - this.emitChange(); - }, - _addBuildTriggerItem: function() { - this.newTags.push({ - name: '', - dockerfile_location: '', - source_name: '', - source_type: 'Branch', - isNew: true - }); - this._resetValidations('buildTags'); - this.emitChange(); - }, - _deleteBuildTriggerItem: function(index) { - this.autoBuildStore.build_tags[index].toDelete = true; - this._resetValidations('buildTags'); - this.emitChange(); - }, - _deleteBuildsNewTagItem: function(index) { - this.newTags[index].toDelete = true; - this._resetValidations('buildTags'); - this.emitChange(); - }, - _updateBuildTriggerItem: function({ index, fieldkey, value}) { - this.autoBuildStore.build_tags[index][fieldkey] = value; - this._resetValidations('buildTags'); - this.emitChange(); - }, - _updateBuildNewTagItem: function({ index, fieldkey, value}) { - this.newTags[index][fieldkey] = value; - this._resetValidations('buildTags'); - this.emitChange(); - }, - _updateFields: function({ field, key, value }) { - this[field][key] = value; - if (field === 'triggerLinkForm') { - this._resetValidations('links'); - } - this.emitChange(); - }, - _saveTagsSuccess: function() { - this.validations.buildTags = { - success: true, - hasError: false, - errors: [] - }; - this.newTags = []; - setTimeout(this._resetValidations.bind(this), 3000, 'buildTags'); - this.emitChange(); - }, - _saveTagsError: function(tag) { - let currentErrors = this.validations.buildTags.errors; - if (tag.error) { - currentErrors.push(`${tag.name}: ${tag.error}`); - } - this.validations.buildTags = { - success: false, - hasError: true, - errors: currentErrors - }; - this.emitChange(); - }, - _receiveTriggerStatus: function(triggerStatus){ - this.triggerStatus = triggerStatus; - this.emitChange(); - }, - _receiveTriggerLogs: function(triggerLogs) { - this.triggerLogs = triggerLogs; - this.emitChange(); - }, - _triggerByTagAttempt: function() { - this.STATUS = STATUS.ATTEMPTING; - this.emitChange(); - }, - _triggerByTagError: function(err) { - this.validations.trigger.error = err; - setTimeout(this._clearTriggerStatus.bind(this), 5000); - this.emitChange(); - }, - _triggerByTagSuccess: function(success) { - this.validations.trigger.success = success; - setTimeout(this._clearTriggerStatus.bind(this), 5000); - this.emitChange(); - }, - _clearTriggerStatus: function() { - this.validations.trigger.success = ''; - this.validations.trigger.error = ''; - this.STATUS = STATUS.DEFAULT; - this.emitChange(); - }, - getState: function() { - return { - autoBuildStore: this.autoBuildStore, - autoBuildBlankSlate: this.autoBuildBlankSlate, - autoBuildLinks: this.autoBuildLinks, - autoTriggerForm: this.autoTriggerForm, - triggerStatus: this.triggerStatus, - triggerLinkForm: this.triggerLinkForm, - triggerLogs: this.triggerLogs, - validations: this.validations, - newTags: this.newTags, - STATUS: this.STATUS - }; - }, - dehydrate: function() { - return this.getState(); - }, - rehydrate: function(state) { - this.autoBuildStore = state.autoBuildStore; - this.autoBuildLinks = state.autoBuildLinks; - this.autoTriggerForm = state.autoTriggerForm; - this.triggerStatus = state.triggerStatus; - this.triggerLinkForm = state.triggerLinkForm; - this.triggerLogs = state.triggerLogs; - this.validations = state.validations; - this.newTags = state.newTags; - this.STATUS = state.STATUS; - } -}); - -module.exports = AutoBuildSettingsStore; diff --git a/app/scripts/stores/AutobuildConfigStore.js b/app/scripts/stores/AutobuildConfigStore.js deleted file mode 100644 index b4f8190d18..0000000000 --- a/app/scripts/stores/AutobuildConfigStore.js +++ /dev/null @@ -1,134 +0,0 @@ -'use strict'; -import createStore from 'fluxible/addons/createStore'; -import forEach from 'lodash/collection/forEach'; -import isString from 'lodash/lang/isString'; -import { STATUS } from './common/Constants'; - -var AutobuildConfigStore = createStore({ - storeName: 'AutobuildConfigStore', - handlers: { - ATTEMPTING_AUTOBUILD_CREATION: '_autobuildCreateAttempt', - AUTOBUILD_ERROR: '_autobuildConfigError', - AUTOBUILD_BAD_REQUEST: '_autobuildBadRequest', - AUTOBUILD_UNAUTHORIZED: '_autobuildUnauthorized', - AUTOBUILD_SUCCESS: '_autobuildSuccess', - AUTOBUILD_FORM_UPDATE_FIELD_WITH_VALUE: '_updateFormField', - SELECT_SOURCE_REPO: '_selectSourceRepo', - CLEAR_AUTOBUILD_FORM_ERRORS: '_clearErrorStates', - INITIALIZE_AUTOBUILD_FORM: '_initializeForm', - RECEIVE_PRIVATE_REPOSTATS: '_getPrivateDefault' - }, - initialize: function() { - this.name = ''; - this.namespace = ''; - this.description = ''; - this.isPrivate = 'public'; - this.provider = ''; - this.sourceRepoName = ''; - this.active = true; - this.error = {}; - this.success = ''; - this.STATUS = STATUS.DEFAULT; - }, - _autobuildConfigError: function(err) { - //TODO: handle config error here - this.error.general = 'An error occurred while configuring your automated build. Please try again later.'; - setTimeout(this._clearErrorStates.bind(this), 5000); - this.emitChange(); - }, - _autobuildCreateAttempt: function() { - this.error.buildTags = ''; - this.STATUS = STATUS.ATTEMPTING; - this.emitChange(); - }, - _autobuildBadRequest: function(err) { - forEach(err, (val, key) => { - this.error[key] = val.toString(); - }); - - //For build_tags, make it a global error - if (err.build_tags) { - this.error.buildTags = 'Invalid character(s) provided in build tags configuration. Please check your input.'; - } - - if (err.detail || isString(err)) { - this.error.detail = err.detail || err; - } - - this.STATUS = STATUS.DEFAULT; - this.emitChange(); - }, - _autobuildUnauthorized: function(err) { - this.error.general = 'You have no permissions to create an automated build in this namespace.'; - setTimeout(this._clearErrorStates.bind(this), 5000); - this.STATUS = STATUS.DEFAULT; - this.emitChange(); - }, - _autobuildSuccess: function(err) { - this.success = 'Successfully configured an automated build repository.'; - this.STATUS = STATUS.SUCCESSFUL; - setTimeout(this._clearErrorStates.bind(this), 5000); - this.emitChange(); - }, - _clearErrorStates: function() { - this.error = {}; - this.success = ''; - this.STATUS = STATUS.DEFAULT; - this.emitChange(); - }, - _getPrivateDefault: function(stats) { - this.isPrivate = stats.default_repo_visibility; - }, - _initializeForm: function({ name, namespace }) { - this.name = name; - this.namespace = namespace; - this.description = ''; - }, - _selectSourceRepo: function(repo) { - this.sourceRepoName = repo.full_name; - this.emitChange(); - }, - _updateFormField: function({fieldKey, fieldValue}) { - this[fieldKey] = fieldValue; - if (fieldKey === 'name' || fieldKey === 'namespace') { - delete this.error.dockerhub_repo_name; - } - if (fieldKey === 'description') { - delete this.error.description; - } - delete this.error.detail; - this.STATUS = STATUS.DEFAULT; - this.emitChange(); - }, - getState: function() { - return { - name: this.name, - namespace: this.namespace, - description: this.description, - isPrivate: this.isPrivate, - provider: this.provider, - sourceRepoName: this.sourceRepoName, - active: this.active, - error: this.error, - success: this.success, - STATUS: this.STATUS - }; - }, - dehydrate: function() { - return this.getState(); - }, - rehydrate: function(state) { - this.name = state.name; - this.namespace = state.namespace; - this.description = state.description; - this.isPrivate = state.isPrivate; - this.provider = state.provider; - this.sourceRepoName = state.sourceRepoName; - this.active = state.active; - this.error = state.error; - this.success = state.success; - this.STATUS = state.STATUS; - } -}); - -module.exports = AutobuildConfigStore; diff --git a/app/scripts/stores/AutobuildSourceRepositoriesStore.js b/app/scripts/stores/AutobuildSourceRepositoriesStore.js deleted file mode 100644 index 2b2448afb4..0000000000 --- a/app/scripts/stores/AutobuildSourceRepositoriesStore.js +++ /dev/null @@ -1,46 +0,0 @@ -'use strict'; -import createStore from 'fluxible/addons/createStore'; -import _ from 'lodash'; - -var AutobuildSourceRepositoriesStore = createStore({ - storeName: 'AutobuildSourceRepositoriesStore', - handlers: { - RECEIVE_LINKED_REPO_SOURCES: '_receiveLinkedRepos', - LINKED_REPO_SOURCES_ERROR: '_linkedReposError', - SET_LINKED_REPO_TYPE: '_setType' - }, - initialize: function() { - this.repos = []; - this.type = ''; - this.error = ''; - }, - _setType: function(type) { - this.type = type; - this.emitChange(); - }, - _receiveLinkedRepos: function(linkedRepos) { - this.repos = linkedRepos; - this.emitChange(); - }, - _linkedReposError: function(err) { - this.error = 'Please check if you have any repositories setup on ' + this.type + '.'; - this.emitChange(); - }, - getState: function() { - return { - repos: this.repos, - type: this.type, - error: this.error - }; - }, - dehydrate: function() { - return this.getState(); - }, - rehydrate: function(state) { - this.repos = state.repos; - this.type = state.type; - this.error = state.error; - } -}); - -module.exports = AutobuildSourceRepositoriesStore; diff --git a/app/scripts/stores/AutobuildStore.js b/app/scripts/stores/AutobuildStore.js deleted file mode 100644 index b012f99a60..0000000000 --- a/app/scripts/stores/AutobuildStore.js +++ /dev/null @@ -1,54 +0,0 @@ -'use strict'; -import createStore from 'fluxible/addons/createStore'; -import _ from 'lodash'; - -var AutobuildStore = createStore({ - storeName: 'AutobuildStore', - handlers: { - RECEIVE_SOURCE_REPOS: '_receiveSourceRepos', - RECEIVE_SOURCE_ACCOUNTS: '_receiveSourceAccount' - }, - initialize: function() { - this.githubAccount = null; - this.githubRepos = []; - this.bitbucketAccount = null; - this.bitbucketRepos = []; - this.gitlabAccount = null; - this.gitlabRepos = []; - }, - _receiveSourceRepos: function(res) { - this.githubRepos = res.github.detail ? [] : res.github; - this.bitbucketRepos = res.bitbucket.detail ? [] : res.bitbucket; - this.gitlabRepos = res.gitlab.detail ? [] : res.gitlab; - this.emitChange(); - }, - _receiveSourceAccount: function(res) { - this.githubAccount = res.github.detail ? null : res.github; - this.bitbucketAccount = res.bitbucket.detail ? null : res.bitbucket; - this.gitlabAccount = res.gitlab.detail ? null : res.gitlab; - this.emitChange(); - }, - getState: function() { - return { - githubAccount: this.githubAccount, - githubRepos: this.githubRepos, - bitbucketAccount: this.bitbucketAccount, - bitbucketRepos: this.bitbucketRepos, - gitlabAccount: this.gitlabAccount, - gitlabRepos: this.gitlabRepos - }; - }, - dehydrate: function() { - return this.getState(); - }, - rehydrate: function(state) { - this.githubAccount = state.githubAccount; - this.githubRepos = state.githubRepos; - this.bitbucketAccount = state.bitbucketAccount; - this.bitbucketRepos = state.bitbucketRepos; - this.gitlabAccount = state.gitlabAccount; - this.gitlabRepos = state.gitlabRepos; - } -}); - -module.exports = AutobuildStore; diff --git a/app/scripts/stores/AutobuildTagsStore.js b/app/scripts/stores/AutobuildTagsStore.js deleted file mode 100644 index 56629f1ca7..0000000000 --- a/app/scripts/stores/AutobuildTagsStore.js +++ /dev/null @@ -1,50 +0,0 @@ -'use strict'; -import createStore from 'fluxible/addons/createStore'; -import _ from 'lodash'; - -var AutobuildTagsStore = createStore({ - storeName: 'AutobuildTagsStore', - handlers: { - AUTOBUILD_TAGS_ERROR: '_autobuildTagsError' - }, - initialize: function() { - //tags is an array of tag - //{ dockerfile_location, source_type['Tag' or 'Branch'], source_name[eg. master] } - this.tags = []; - }, - addTag: function(tag) { - //tag - //{ - // id: 'row-1' - // sourceName: 'master' - // fileLocation: '/' - // buildTag: 'latest', - // sourceType: 'Branch' - //} - this.tags.push(tag); - }, - removeTag: function(id) { - _.remove(this.tags, function(tag) { - return (tag.id === id); - }); - }, - setTagState: function(id, state) { - var tagToUpdate = _.find(this.tags, function(tag) { - return tag.id === id; - }); - _.merge(tagToUpdate, state); - }, - getState: function() { - return { - tags: this.tags - }; - }, - dehydrate: function() { - return this.getState(); - }, - rehydrate: function(state) { - this.tags = state.tags; - } -}); - -module.exports = AutobuildTagsStore; diff --git a/app/scripts/stores/AutobuildTriggerByTagStore.js b/app/scripts/stores/AutobuildTriggerByTagStore.js deleted file mode 100644 index b3c16f81a1..0000000000 --- a/app/scripts/stores/AutobuildTriggerByTagStore.js +++ /dev/null @@ -1,91 +0,0 @@ -'use strict'; -import createStore from 'fluxible/addons/createStore'; -import findIndex from 'lodash/array/findIndex'; -import map from 'lodash/collection/map'; -import { STATUS } from './common/Constants'; - -var AutobuildTriggerByTagStore = createStore({ - storeName: 'AutobuildTriggerByTagStore', - handlers: { - INITIALIZE_AB_TRIGGERS: '_initTriggers', - AB_TRIGGER_BY_TAG_ERROR: '_triggerByTagError', - AB_TRIGGER_BY_TAG_SUCCESS: '_triggerByTagSuccess', - ATTEMPT_TRIGGER_BY_TAG: '_triggerByTagAttempt' - }, - initialize: function() { - this.triggers = []; - this.tagStatuses = []; - }, - _initTriggers: function(tags) { - //on load of the build settings page - this.initialize(); - - this.triggers = map(tags, (tag) => { - return { - id: tag.id, - success: '', - error: '' - }; - }); - - this.tagStatuses = map(tags, (tag) => { - return { - id: tag.id, - status: STATUS.DEFAULT - }; - }); - this.emitChange(); - }, - _findIndices: function(id) { - const statusIndex = findIndex(this.tagStatuses, (s) => { - return s.id === id; - }); - const triggerIndex = findIndex(this.triggers, (t) => { - return t.id === id; - }); - return {statusIndex, triggerIndex}; - }, - _triggerByTagAttempt: function(id) { - const {statusIndex, triggerIndex} = this._findIndices(id); - this.tagStatuses[statusIndex].status = STATUS.ATTEMPTING; - this.triggers[triggerIndex].error = ''; - this.triggers[triggerIndex].success = ''; - this.emitChange(); - }, - _triggerByTagError: function(errObj) { - const {id, error} = errObj; - const { triggerIndex } = this._findIndices(id); - this.triggers[triggerIndex].error = error; - setTimeout(this._clearTriggerStatus.bind(this, id), 3000); - this.emitChange(); - }, - _triggerByTagSuccess: function(successObj) { - const {id, success} = successObj; - const { triggerIndex } = this._findIndices(id); - this.triggers[triggerIndex].success = success; - setTimeout(this._clearTriggerStatus.bind(this, id), 3000); - this.emitChange(); - }, - _clearTriggerStatus: function(id) { - const {statusIndex, triggerIndex} = this._findIndices(id); - this.tagStatuses[statusIndex].status = STATUS.DEFAULT; - this.triggers[triggerIndex].error = ''; - this.triggers[triggerIndex].success = ''; - this.emitChange(); - }, - getState: function() { - return { - triggers: this.triggers, - tagStatuses: this.tagStatuses - }; - }, - dehydrate: function() { - return this.getState(); - }, - rehydrate: function(state) { - this.triggers = state.triggers; - this.tagStatuses = state.tagStatuses; - } -}); - -module.exports = AutobuildTriggerByTagStore; diff --git a/app/scripts/stores/BillingInfoFormStore.js b/app/scripts/stores/BillingInfoFormStore.js deleted file mode 100644 index 19473595c5..0000000000 --- a/app/scripts/stores/BillingInfoFormStore.js +++ /dev/null @@ -1,184 +0,0 @@ -'use strict'; -import createStore from 'fluxible/addons/createStore'; -import _ from 'lodash'; -import { STATUS } from './billingformstore/Constants'; -var debug = require('debug')('STORE::BillingInfoFormStore'); - -var BillingInfoFormStore = createStore({ - storeName: 'BillingInfoFormStore', - handlers: { - BILLING_ACCOUNT_EXISTS: '_accountExists', - BILLING_INFO_EXISTS: '_billingInfoExists', - BILLING_ERRORS: '_updateErrors', - BILLING_INFO_UPDATE_FIELD_WITH_VALUE: '_updateBillingInfoForm', - BILLING_SUBMIT_ERROR: '_submitErrors', - BILLING_SUBMIT_START: '_submitStart', - BILLING_SUBMIT_SUCCESS: '_submitSuccess', - CLEAR_BILLING_FORM: '_clearBillingForm', - GET_RECURLY_ERROR: '_updateRecurlyErrors', - LOGOUT: '_clearStore', - RECEIVE_BILLING_INFO: '_receiveBillingInfo', - UPDATE_COUPON_VALUE: '_updateCouponValue' - }, - initialize: function() { - var D = new Date(); - var month = 1; - var year = D.getFullYear(); - this.billforwardId = ''; - this.accountInfo = { // Billing profile account - account_code: '', - username: '', - email: '', - first_name: '', - last_name: '', - company_name: '', - hasError: false, - newBilling: true - }; - this.billingInfo = { // Billing card information - first_name: '', - last_name: '', - address1: '', - address2: '', - country: '', - state: '', - zip: '', - city: '', - last_four: '', - card_type: '', - month: '', - year: '', - newBilling: true - }; - this.card = { - number: '', - cvv: '', - month: month, - year: year, - last_four: null, - type: '', - coupon_code: '', - coupon: 0 - }; - this.errorMessage = ''; - this.fieldErrors = { - number: false, - expiry: false, - cvv: false, - coupon_code: false, - first_name: false, - last_name: false, - address1: false, - country: false, - state: false, - zip: false, - city: false, - month: false, - year: false - }; - this.STATUS = STATUS.DEFAULT; - }, - _accountExists: function() { - this.accountInfo.newBilling = false; - this.emitChange(); - }, - _billingInfoExists: function() { - this.billingInfo.newBilling = false; - this.emitChange(); - }, - _clearStore: function() { - this.initialize(); - }, - _receiveBillingInfo: function(payload) { - this.initialize(); - if (payload.billingInfo && payload.billingInfo.last_four) { - var cardInfo = { - last_four: payload.billingInfo.last_four, - type: payload.billingInfo.card_type, - month: payload.billingInfo.month, - year: payload.billingInfo.year - }; - } - _.merge(this.billingInfo, payload.billingInfo); - _.merge(this.accountInfo, payload.accountInfo); - _.merge(this.card, cardInfo); - this.billforwardId = payload.billforwardId; - this.emitChange(); - }, - _submitErrors: function(message) { - this.STATUS = STATUS.FORM_ERROR; - this.errorMessage = message; - this.emitChange(); - }, - _submitSuccess: function() { - this.STATUS = STATUS.SUCCESS; - this.errorMessage = ''; - this.emitChange(); - }, - _submitStart: function() { - this.STATUS = STATUS.ATTEMPTING; - this.errorMessage = ''; - this.emitChange(); - }, - _updateBillingInfoForm: function({ field, fieldKey, fieldValue }) { - if (field === 'billing') { - this.billingInfo[fieldKey] = fieldValue; - } else if (field === 'account') { - this.accountInfo[fieldKey] = fieldValue; - } else if (field === 'card') { - this.card[fieldKey] = fieldValue; - } - this.emitChange(); - }, - _updateErrors: function(hasError) { - this.STATUS = STATUS.FORM_ERROR; - _.merge(this.fieldErrors, hasError.fieldErrors); - _.merge(this.accountInfo, hasError.accountErr); - this.errorMessage = 'Please make sure all fields are valid.'; - this.emitChange(); - }, - _updateRecurlyErrors: function(error) { - const errorFields = error.fields; - debug('Recurly Form errors', errorFields); - const fieldErrors = { - number: _.includes(errorFields, 'number'), - expiry: _.includes(errorFields, 'month') || _.includes(errorFields, 'year'), - cvv: _.includes(errorFields, 'cvv'), - first_name: _.includes(errorFields, 'first_name'), - last_name: _.includes(errorFields, 'last_name') - }; - _.merge(this.fieldErrors, fieldErrors); - this.STATUS = STATUS.FORM_ERROR; - this.errorMessage = error.message; - this.emitChange(); - }, - _updateCouponValue: function(value) { - this.card.coupon = value; - this.emitChange(); - }, - getState: function() { - return { - billforwardId: this.billforwardId, - accountInfo: this.accountInfo, - billingInfo: this.billingInfo, - card: this.card, - errorMessage: this.errorMessage, - fieldErrors: this.fieldErrors, - STATUS: this.STATUS - }; - }, - dehydrate: function() { - return this.getState(); - }, - rehydrate: function(state) { - this.billforwardId = state.billforwardId; - this.accountInfo = state.accountInfo; - this.billingInfo = state.billingInfo; - this.card = state.card; - this.errorMessage = state.errorMessage; - this.fieldErrors = state.fieldErrors; - this.STATUS = state.STATUS; - } -}); - -module.exports = BillingInfoFormStore; diff --git a/app/scripts/stores/BillingPlansStore.js b/app/scripts/stores/BillingPlansStore.js deleted file mode 100644 index 3a25234628..0000000000 --- a/app/scripts/stores/BillingPlansStore.js +++ /dev/null @@ -1,128 +0,0 @@ -'use strict'; -import createStore from 'fluxible/addons/createStore'; -import _ from 'lodash'; - -var BillingPlansStore = createStore({ - storeName: 'BillingPlansStore', - handlers: { - RESET_BILLING_PLANS: '_clearStore', - RECEIVE_BILLING_INFO: '_receiveBillingInfo', - RECEIVE_BILLING_SUBSCRIPTION: '_receiveBillingSubscription', - RECEIVE_INVOICES: '_receiveInvoices', - RESET_CURRENT_PLAN: '_resetCurrentPlan', - UPDATE_PLAN_START: '_updatePlanStart', - UPDATE_PLAN_ERROR: '_updatePlanErr', - DELETE_SUBSCRIPTION_ERR: '_updatePlanErr', - DELETE_SUBSCRIPTION_SUCCESS: '_unsubscribeComplete', - UNSUBSCRIBE_SUBSCRIPTION: '_unsubscribe', // UNUSED - deprecated - UNSUBSCRIBE_PACKAGE: '_unsubscribePackage', // UNUSED - deprecated - UNSUBSCRIBE_PLAN: '_unsubscribePlan', // UNUSED - deprecated - LOGOUT: '_clearStore' - }, - initialize: function() { - this.currentPlan = {}; - this.accountInfo = { - account_code: '', - username: '', - email: '', - first_name: '', - last_name: '', - company_name: '', - hasError: false, - newBilling: true - }; - this.billingInfo = { - first_name: '', - last_name: '', - address1: '', - address2: '', - country: '', - state: '', - zip: '', - city: '', - last_four: '', - card_type: '', - month: '', - year: '', - newBilling: true - }; - this.invoices = []; - this.plansError = ''; - this.unsubscribing = ''; - this.updatePlan = ''; - }, - _clearStore: function() { - this.initialize(); - }, - _receiveBillingInfo: function(payload) { - this.initialize(); - _.merge(this.billingInfo, payload.billingInfo); - _.merge(this.accountInfo, payload.accountInfo); - _.merge(this.currentPlan, payload.currentPlan); - this.emitChange(); - }, - _receiveBillingSubscription: function(payload) { - _.merge(this.currentPlan, payload.currentPlan); - this.updatePlan = ''; - this.emitChange(); - }, - _receiveInvoices: function(payload) { - this.invoices = payload.invoices; - this.emitChange(); - }, - _resetCurrentPlan: function(payload) { - this.currentPlan = payload.currentPlan; - this.emitChange(); - }, - _unsubscribe: function() { // UNUSED - deprecated - this.unsubscribing = 'subscription'; - this.emitChange(); - }, - _unsubscribePackage: function() { // UNUSED - deprecated - this.unsubscribing = 'package'; - this.emitChange(); - }, - _unsubscribePlan: function() { // UNUSED - deprecated - this.unsubscribing = 'plan'; - this.emitChange(); - }, - _unsubscribeComplete: function() { // UNUSED - deprecated - this.unsubscribing = ''; - this.emitChange(); - }, - _updatePlanStart: function(payload) { - this.updatePlan = payload; - this.emitChange(); - }, - _updatePlanErr: function(payload) { - this.unsubscribing = ''; - this.updatePlan = ''; - this.plansError = payload; - this.emitChange(); - }, - getState: function() { - return { - currentPlan: this.currentPlan, - accountInfo: this.accountInfo, - billingInfo: this.billingInfo, - invoices: this.invoices, - plansError: this.plansError, - unsubscribing: this.unsubscribing, - updatePlan: this.updatePlan - }; - }, - dehydrate: function() { - return this.getState(); - }, - rehydrate: function(state) { - this.currentPlan = state.currentPlan; - this.accountInfo = state.accountInfo; - this.billingInfo = state.billingInfo; - this.invoices = state.invoices; - this.plansError = state.plansError; - this.unsubscribing = state.unsubscribing; - this.updatePlan = state.updatePlan; - } -}); - -module.exports = BillingPlansStore; diff --git a/app/scripts/stores/BitbucketLinkStore.js b/app/scripts/stores/BitbucketLinkStore.js deleted file mode 100644 index 5d4afc6c37..0000000000 --- a/app/scripts/stores/BitbucketLinkStore.js +++ /dev/null @@ -1,59 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -var debug = require('debug')('BitbucketLinkStore'); - -var BitbucketLinkStore = createStore({ - storeName: 'BitbucketLinkStore', - handlers: { - RECEIVE_BITBUCKET_AUTH_URL: '_receiveUrl', - BITBUCKET_AUTH_URL_ERROR: '_urlError', - BITBUCKET_ASSOCIATE_ERROR: '_associateError' - }, - initialize: function() { - this.authURL = ''; - this.error = ''; - }, - _associateError: function(err) { - debug(err); - if (err.detail) { - this.error = err.detail; - } else { - this.error = 'Error linking your account to Bitbucket. Please check that you do not have the same Bitbucket account linked to another Docker Hub account.'; - } - this.emitChange(); - setTimeout(this._clearError.bind(this), 5000); - }, - _receiveUrl: function(res) { - this.authURL = res.bitbucket_authorization_url; - this.emitChange(); - }, - _urlError: function(err) { - debug(err); - this.error = 'Error linking your account to bitbucket.'; - this.emitChange(); - setTimeout(this._clearError.bind(this), 5000); - }, - _clearError: function() { - this.error = ''; - this.emitChange(); - }, - setURL: function(url) { - this.authURL = url; - }, - getState: function() { - return { - authURL: this.authURL, - error: this.error - }; - }, - rehydrate: function(state) { - this.authURL = state.authURL; - this.error = state.error; - }, - dehydrate: function() { - return this.getState(); - } -}); - -module.exports = BitbucketLinkStore; diff --git a/app/scripts/stores/ChangePasswordStore.js b/app/scripts/stores/ChangePasswordStore.js deleted file mode 100644 index f9c210622c..0000000000 --- a/app/scripts/stores/ChangePasswordStore.js +++ /dev/null @@ -1,64 +0,0 @@ -'use strict'; -import createStore from 'fluxible/addons/createStore'; -const debug = require('debug')('stores: ChangePasswordStore'); - -var ChangePasswordStore = createStore({ - storeName: 'ChangePasswordStore', - handlers: { - CHANGE_PASS_UPDATE: '_updateStore', - CHANGE_PASS_SUCCESS: '_changePassSuccess', - CHANGE_PASS_CLEAR: '_clearStore', - RESET_PASSWORD_SUCCESSFUL: '_changePassSuccess', - RESET_PASSWORD_ERROR: '_changePassError' - }, - initialize: function() { - this.oldpass = ''; - this.newpass = ''; - this.confpass = ''; - this.reset = false; - this.hasErr = false; - this.err = ''; - }, - _updateStore: function(payload) { - this.reset = false; - this.hasErr = false; - this.err = ''; - this.oldpass = payload.oldpass; - this.newpass = payload.newpass; - this.confpass = payload.confpass; - this.emitChange(); - }, - _changePassSuccess: function() { - this._clearStore(); - this.reset = true; - this.emitChange(); - }, - _changePassError: function(error) { - this._clearStore(); - this.hasErr = true; - this.err = error; - this.emitChange(); - }, - _clearStore: function() { - this.oldpass = ''; - this.newpass = ''; - this.confpass = ''; - this.reset = false; - this.hasErr = false; - this.err = ''; - this.emitChange(); - }, - getState: function() { - return { - oldpass: this.oldpass, - newpass: this.newpass, - confpass: this.confpass, - reset: this.reset, - hasErr: this.hasErr, - err: this.err - }; - } - -}); - -module.exports = ChangePasswordStore; diff --git a/app/scripts/stores/CloudBillingStore.js b/app/scripts/stores/CloudBillingStore.js deleted file mode 100644 index 4489827ae7..0000000000 --- a/app/scripts/stores/CloudBillingStore.js +++ /dev/null @@ -1,43 +0,0 @@ -'use strict'; -import createStore from 'fluxible/addons/createStore'; - -var BillingPlansStore = createStore({ - storeName: 'CloudBillingStore', - handlers: { - RESET_CLOUD_BILLING_PLANS: '_clearStore', - RECEIVE_CLOUD_BILLING_INFO: '_receiveBillingInfo', - LOGOUT: '_clearStore' - }, - initialize: function() { - this.currentPlan = {}; - this.billingInfo = {}; - this.accountInfo = {}; - }, - _clearStore: function() { - this.initialize(); - this.emitChange(); - }, - _receiveBillingInfo: function(payload) { - this.billingInfo = payload.billingInfo; - this.accountInfo = payload.accountInfo; - this.currentPlan = payload.currentPlan; - this.emitChange(); - }, - getState: function() { - return { - currentPlan: this.currentPlan, - accountInfo: this.accountInfo, - billingInfo: this.billingInfo - }; - }, - dehydrate: function() { - return this.getState(); - }, - rehydrate: function(state) { - this.currentPlan = state.currentPlan; - this.accountInfo = state.accountInfo; - this.billingInfo = state.billingInfo; - } -}); - -module.exports = BillingPlansStore; diff --git a/app/scripts/stores/CloudCouponStore.js b/app/scripts/stores/CloudCouponStore.js deleted file mode 100644 index c3bb7add7a..0000000000 --- a/app/scripts/stores/CloudCouponStore.js +++ /dev/null @@ -1,54 +0,0 @@ -'use strict'; -import createStore from 'fluxible/addons/createStore'; -import _ from 'lodash'; - -var CloudCouponStore = createStore({ - storeName: 'CloudCouponStore', - handlers: { - RECEIVE_BILLING_INFO: '_clearStore', - CLEAR_CLOUD_COUPON: '_clearStore', - UPDATE_COUPON_VALUE: '_updateDiscountValue', - BILLING_INFO_UPDATE_FIELD_WITH_VALUE: '_updateCouponCode', - BILLING_ERRORS: '_updateErrors' - }, - initialize: function() { - this.couponCode = ''; - this.discountValue = 0; - this.hasError = false; - }, - _clearStore: function() { - this.initialize(); - this.emitChange(); - }, - _updateCouponCode: function({field, fieldKey, fieldValue}) { - this.couponCode = fieldKey === 'coupon_code' ? fieldValue : this.couponValue; - this.emitChange(); - }, - _updateDiscountValue: function(discount) { - this.discountValue = discount; - this.emitChange(); - }, - _updateErrors: function({fieldErrors}) { - if (_.has(fieldErrors, 'coupon_code')) { - this.hasError = fieldErrors.coupon_code; - } - this.emitChange(); - }, - getState: function() { - return { - couponCode: this.couponCode, - discountValue: this.discountValue, - hasError: this.hasError - }; - }, - dehydrate: function() { - return this.getState(); - }, - rehydrate: function(state) { - this.couponCode = state.couponCode; - this.discountValue = state.discountValue; - this.hasError = state.hasError; - } -}); - -module.exports = CloudCouponStore; diff --git a/app/scripts/stores/ConvertToOrgStore.js b/app/scripts/stores/ConvertToOrgStore.js deleted file mode 100644 index f100be9945..0000000000 --- a/app/scripts/stores/ConvertToOrgStore.js +++ /dev/null @@ -1,41 +0,0 @@ -'use strict'; -import createStore from 'fluxible/addons/createStore'; -var debug = require('debug')('stores: ConvertToOrgStore'); - -export default createStore({ - storeName: 'ConvertToOrgStore', - handlers: { - CONVERT_TO_ORG_BAD_REQUEST: '_badRequest', - UPDATE_TO_ORG_OWNER: '_updateOwner' - }, - initialize: function() { - this.convertError = false; - this.error = {}; - this.newOwner = ''; - }, - _badRequest: function(error) { - this.convertError = true; - this.error = error; - this.emitChange(); - }, - _updateOwner: function(payload) { - this.newOwner = payload.newOwner; - this.convertError = false; - this.emitChange(); - }, - getState: function() { - return { - convertError: this.convertError, - error: this.error, - newOwner: this.newOwner - }; - }, - dehydrate: function() { - return this.getState(); - }, - rehydrate: function(state) { - this.convertError = state.convertError; - this.error = state.error; - this.newOwner = state.newOwner; - } -}); diff --git a/app/scripts/stores/CreateRepositoryFormStore.js b/app/scripts/stores/CreateRepositoryFormStore.js deleted file mode 100644 index e604fa6a50..0000000000 --- a/app/scripts/stores/CreateRepositoryFormStore.js +++ /dev/null @@ -1,147 +0,0 @@ -'use strict'; - -import _ from 'lodash'; -import { STATUS } from './common/Constants'; -import createStore from 'fluxible/addons/createStore'; -var debug = require('debug')('CreateRepositoryFormStore'); - -var noErrorObj = { - hasError: false, - error: '' -}; - -export default createStore({ - storeName: 'CreateRepositoryFormStore', - handlers: { - CREATE_REPO_CLEAR_FORM: 'initialize', - CREATE_REPO_UPDATE_FIELD_WITH_VALUE: '_updateFieldWithValue', - CREATE_REPO_ATTEMPT_START: '_attemptStart', - CREATE_REPO_BAD_REQUEST: '_badRequest', - CREATE_REPO_SUCCESS: '_success', - CREATE_REPO_FACEPALM: '_facepalm', - CREATE_REPO_RECEIVE_NAMESPACES: '_receiveNamespaces' - }, - initialize() { - this.STATUS = STATUS.DEFAULT; - - this.namespaces = []; - this.globalFormError = ''; - - this.fields = { - user: {}, - namespace: {}, - name: {}, - description: {}, - full_description: {}, - is_private: {} - }; - - this.values = { - user: '', - namespace: '', - name: '', - description: '', - full_description: '', - is_private: true - }; - }, - _receiveNamespaces({ - namespaces, selectedNamespace - }) { - debug('receiving namespaces', namespaces, selectedNamespace); - /** - * namespaces is equivalent to the response in the namespaces API call - */ - this.namespaces = namespaces.namespaces; - if(_.includes(namespaces.namespaces, selectedNamespace)) { - this.values.namespace = selectedNamespace; - } else { - this.values.namespace = namespaces.namespaces[0]; - } - this.emitChange(); - }, - _facepalm() { - // this happens if things are screwed and we can't recover gracefully - this.STATUS = STATUS.FACEPALM; - this.emitChange(); - }, - _clearForm() { - this.initialize(); - this.emitChange(); - }, - _updateFieldWithValue({fieldKey, fieldValue}) { - debug(fieldKey, fieldValue); - this.fields[fieldKey].hasError = false; - this.fields[fieldKey].error = ''; - this.globalFormError = ''; - this.values[fieldKey] = fieldValue; - this.emitChange(); - }, - _attemptStart() { - this.STATUS = STATUS.ATTEMPTING; - this.emitChange(); - }, - _success() { - this.STATUS = STATUS.SUCCESSFUL_SIGNUP; - this.emitChange(); - }, - _badRequest(obj) { - /** - * This function expects keys which match the `this.fields` keys - * with an array of errors: - * - * { - * orgname: ['this field is required'] - * } - */ - let shouldEmitChange = false; - // So far obj.detail is only returned when there are no more private repo's - // We really need to update the response from the api - if (obj.detail) { - obj.is_private = [obj.detail]; - } - - // cycle through the possible form fields - this.fields = _.mapValues(this.fields, function (errorObject, key) { - if(_.has(obj, key)) { - shouldEmitChange = true; - return { - hasError: !!obj[key], - error: obj[key][0] - }; - } else { - return errorObject; - } - }); - /** - * __all__ occurs when "Repository with this Name and Namespace already exists." - */ - if(obj.__all__) { - this.globalFormError = obj.__all__[0]; - shouldEmitChange = true; - } - - if(shouldEmitChange) { - this.emitChange(); - } - }, - getState() { - return { - fields: this.fields, - values: this.values, - STATUS: this.STATUS, - namespaces: this.namespaces, - globalFormError: this.globalFormError - }; - }, - dehydrate() { - return this.getState(); - }, - rehydrate(state) { - this.fields = state.fields; - this.values = state.values; - this.namespaces = state.namespaces; - this.STATUS = state.STATUS; - this.globalFormError = state.globalFormError; - } -}); diff --git a/app/scripts/stores/DashboardContribsStore.js b/app/scripts/stores/DashboardContribsStore.js deleted file mode 100644 index cbdae5356f..0000000000 --- a/app/scripts/stores/DashboardContribsStore.js +++ /dev/null @@ -1,43 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -var debug = require('debug')('DashboardContribsStore'); - -export default createStore({ - storeName: 'DashboardContribsStore', - handlers: { - RECEIVE_CONTRIB: '_receiveContribRepos', - LOGOUT: 'initialize' - }, - initialize: function() { - this.count = 0; - this.contribs = []; - this.next = null; - this.prev = null; - }, - _receiveContribRepos: function(res) { - this.count = res.count; - this.contribs = res.results; - this.next = res.next; - this.prev = res.previous; - this.emitChange(); - }, - getState: function() { - return { - count: this.count, - contribs: this.contribs, - next: this.next, - prev: this.prev - }; - }, - dehydrate: function() { - return this.getState(); - }, - rehydrate: function(state) { - this.count = state.count; - this.contribs = state.contribs; - this.next = state.next; - this.prev = state.prev; - } -}); - diff --git a/app/scripts/stores/DashboardMembersStore.js b/app/scripts/stores/DashboardMembersStore.js deleted file mode 100644 index 0b2df77622..0000000000 --- a/app/scripts/stores/DashboardMembersStore.js +++ /dev/null @@ -1,73 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -import _ from 'lodash'; -var debug = require('debug')('DashboardMembersStore'); -import { STATUS } from './orgteamstore/Constants'; - -var DashboardMembersStore = createStore({ - storeName: 'DashboardMembersStore', - handlers: { - RECEIVE_DASHBOARD_TEAM_MEMBERS: '_receiveDashboardTeamMembers', - ORG_DASHBOARD_MEMBERS_ERROR: '_errorReceivingMembers', - TEAM_MEMBER_ERROR: '_teamMemberError', - TEAM_MEMBER_BAD_REQUEST: '_teamMemberBadRequest', - TEAM_MEMBER_UNAUTHORIZED: '_teamMemberUnauthorized', - CLEAR_MEMBER_ERROR: '_clearErrorStates' - }, - initialize() { - this.members = []; - this.count = 0; - this.error = {}; - this.STATUS = STATUS.DEFAULT; - }, - _errorReceivingMembers(err) { - debug(err); - }, - _receiveDashboardTeamMembers(members) { - debug(members); - this.members = members; - this.count = members.length; - this.emitChange(); - }, - _teamMemberError: function(err) { - this.STATUS = STATUS.MEMBER_ERROR; - this.STATUS = STATUS.GENERAL_SERVER_ERROR; - this.error = err; - this.emitChange(); - }, - _teamMemberBadRequest: function(err) { - this.STATUS = STATUS.MEMBER_BAD_REQUEST; - this.error = err; - this.emitChange(); - }, - _teamMemberUnauthorized: function(err) { - this.STATUS = STATUS.MEMBER_UNAUTHORIZED; - this.error = err; - this.emitChange(); - }, - _clearErrorStates: function() { - this.error = {}; - this.STATUS = STATUS.DEFAULT; - this.emitChange(); - }, - getState() { - return { - members: this.members, - count: this.count, - error: this.error, - STATUS: this.STATUS - }; - }, - dehydrate: function() { - return this.getState(); - }, - rehydrate: function(state) { - this.members = state.members; - this.count = state.count; - this.STATUS = state.STATUS; - this.error = state.error; - } -}); - -module.exports = DashboardMembersStore; diff --git a/app/scripts/stores/DashboardNamespacesStore.js b/app/scripts/stores/DashboardNamespacesStore.js deleted file mode 100644 index 35b354f8b6..0000000000 --- a/app/scripts/stores/DashboardNamespacesStore.js +++ /dev/null @@ -1,62 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -var debug = require('debug')('DashboardNamespacesStore'); -import _ from 'lodash'; - -export default createStore({ - storeName: 'DashboardNamespacesStore', - handlers: { - RECEIVE_DASHBOARD_NAMESPACES: '_receiveOrgs', - CURRENT_USER_CONTEXT: '_setContext', - CREATE_REPO_RECEIVE_NAMESPACES: '_receiveOwnedNamespaces' - }, - initialize() { - this.namespaces = []; - this.currentUserContext = ''; - this.ownedNamespaces = []; - }, - _receiveOrgs(res) { - //There are two API calls possible to get namespaces - //`/v2/namespaces` -> returns `res.orgs.namespaces` an object with {namespaces: ['ns1', 'ns2', 'etc']} - //`/v2/orgs` -> returns `res.orgs.results` with all orgs the user has read access on. We merge the `res.user` with this list - if (res.orgs.namespaces) { - this.namespaces = res.orgs.namespaces; - } else if (res.orgs.results && _.isArray(res.orgs.results)) { - var nsArray = _.pluck(res.orgs.results, 'orgname'); - nsArray.unshift(res.user); - this.namespaces = nsArray; - } - this.emitChange(); - }, - _receiveOwnedNamespaces({ - namespaces, selectedNamespace - }) { - debug('receiving namespaces', namespaces, selectedNamespace); - /** - * namespaces is equivalent to the response in the namespaces API call - */ - this.ownedNamespaces = namespaces.namespaces; - this.emitChange(); - }, - _setContext: function({username}) { - this.currentUserContext = username; - this.emitChange(); - }, - getState() { - return { - currentUserContext: this.currentUserContext, - namespaces: this.namespaces, - ownedNamespaces: this.ownedNamespaces - }; - }, - dehydrate() { - return this.getState(); - }, - rehydrate(state) { - this.currentUserContext = state.currentUserContext; - this.namespaces = state.namespaces; - this.ownedNamespaces = state.ownedNamespaces; - } -}); - diff --git a/app/scripts/stores/DashboardReposStore.js b/app/scripts/stores/DashboardReposStore.js deleted file mode 100644 index 1501ffc8a4..0000000000 --- a/app/scripts/stores/DashboardReposStore.js +++ /dev/null @@ -1,69 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -var debug = require('debug')('DashboardReposStore'); -import { STATUS } from './common/Constants'; -const { - ATTEMPTING, - DEFAULT, - SUCCESSFUL -} = STATUS; - -var DashboardReposStore = createStore({ - storeName: 'DashboardReposStore', - handlers: { - RECEIVE_REPOS: '_receiveRepos', - LOGOUT: 'initialize', - DASHBOARD_REPOS_STORE_ATTEMPTING_GET_REPOS: '_startGetRepos', - DASHBOARD_REPOS_STORE_ATTEMPTING_GET_ALL_REPOS: '_startGetAllRepos', - DASHBOARD_REPOS_STORE_RECEIVE_ALL_REPOS_SUCCESS: '_receiveAllRepos' - }, - initialize() { - this.repos = []; - this.count = 0; - this.next = null; - this.prev = null; - this.STATUS = DEFAULT; - }, - getState() { - return { - repos: this.repos, - count: this.count, - next: this.next, - prev: this.prev, - STATUS: this.STATUS - }; - }, - _startGetRepos: function() { - this.STATUS = DEFAULT; - this.emitChange(); - }, - _startGetAllRepos: function() { - this.STATUS = ATTEMPTING; - this.emitChange(); - }, - _receiveRepos(res) { - debug(res); - this.repos = res.results; - this.count = res.count; - this.next = res.next; - this.prev = res.previous; - this.emitChange(); - }, - _receiveAllRepos(res) { - this.STATUS = SUCCESSFUL; - this._receiveRepos(res); - }, - dehydrate() { - return this.getState(); - }, - rehydrate(state) { - this.repos = state.repos; - this.count = state.count; - this.next = state.next; - this.prev = state.prev; - this.STATUS = state.STATUS; - } -}); - -module.exports = DashboardReposStore; diff --git a/app/scripts/stores/DashboardStarsStore.js b/app/scripts/stores/DashboardStarsStore.js deleted file mode 100644 index 2e8da00d21..0000000000 --- a/app/scripts/stores/DashboardStarsStore.js +++ /dev/null @@ -1,43 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -var debug = require('debug')('DashboardStarsStore'); - -export default createStore({ - storeName: 'DashboardStarsStore', - handlers: { - RECEIVE_STARRED: '_receiveStarredRepos', - LOGOUT: 'initialize' - }, - initialize: function() { - this.count = 0; - this.starred = []; - this.next = null; - this.prev = null; - }, - _receiveStarredRepos: function(res) { - this.count = res.count; - this.starred = res.results; - this.next = res.next; - this.prev = res.previous; - this.emitChange(); - }, - getState: function() { - return { - count: this.count, - starred: this.starred, - next: this.next, - prev: this.prev - }; - }, - dehydrate: function() { - return this.getState(); - }, - rehydrate: function(state) { - this.count = state.count; - this.starred = state.starred; - this.next = state.next; - this.prev = state.prev; - } -}); - diff --git a/app/scripts/stores/DashboardStore.js b/app/scripts/stores/DashboardStore.js deleted file mode 100644 index f8702ca5e7..0000000000 --- a/app/scripts/stores/DashboardStore.js +++ /dev/null @@ -1,63 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -var debug = require('debug')('DashboardStore'); - -var DashboardStore = createStore({ - storeName: 'DashboardStore', - handlers: { - RECEIVE_STARRED: '_receiveStarredRepos', - RECEIVE_CONTRIB: '_receiveContribRepos', - RECEIVE_ACTIVITY_FEED: '_receiveActivityFeed', - LOGOUT: 'initialize' - }, - initialize: function() { - this.user = {}; - this.org = ''; - this.starred = []; - this.contribs = []; - this.feed = []; - }, - getInitState: function() { - return { - starred: [], - contribs: [], - org: '', - feed: [], - user: {} - }; - }, - _receiveStarredRepos: function(repos) { - this.starred = repos.results; - this.emitChange(); - }, - _receiveContribRepos: function(repos) { - this.contribs = repos.results; - this.emitChange(); - }, - _receiveActivityFeed: function(feed) { - this.feed = feed; - this.emitChange(); - }, - getState: function() { - return { - starred: this.starred, - contribs: this.contribs, - org: this.org, - feed: this.feed, - user: this.user - }; - }, - dehydrate: function() { - return this.getState(); - }, - rehydrate: function(state) { - this.starred = state.starred; - this.contribs = state.contribs; - this.feed = state.feed; - this.org = state.org; - this.user = state.user; - } -}); - -module.exports = DashboardStore; diff --git a/app/scripts/stores/DashboardTeamsStore.js b/app/scripts/stores/DashboardTeamsStore.js deleted file mode 100644 index 74d1fb2447..0000000000 --- a/app/scripts/stores/DashboardTeamsStore.js +++ /dev/null @@ -1,100 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -import _ from 'lodash'; -import { STATUS } from './orgteamstore/Constants'; -var debug = require('debug')('DashboardTeamsStore'); - -var DashboardTeamsStore = createStore({ - storeName: 'DashboardTeamsStore', - handlers: { - RECEIVE_DASHBOARD_ORG_TEAMS: '_receiveDashboardOrgTeams', - TEAM_ERROR: '_orgTeamError', - TEAM_BAD_REQUEST: '_teamBadRequest', - TEAM_UNAUTHORIZED: '_teamUnauthorized', - UPDATE_TEAM_ERROR: '_updateTeamError', - UPDATE_TEAM_SUCCESS: '_updateTeamSuccess', - TEAM_READ_ONLY: '_isTeamReadOnly' - }, - initialize() { - this.teams = []; - this.count = 0; - this.teamReadOnly = false; - this.errorDetails = {detail: ''}; - this.success = ''; - this.STATUS = STATUS.DEFAULT; - }, - _receiveDashboardOrgTeams(orgTeams) { - debug(orgTeams); - this.teams = _.sortBy(orgTeams.results, 'name'); - this.count = orgTeams.count; - this.emitChange(); - }, - _orgTeamError: function(err) { - this.STATUS = STATUS.TEAM_ERROR; - this.STATUS = STATUS.GENERAL_SERVER_ERROR; - this.errorDetails = {detail: 'Username does not exist or it is invalid.'}; - this.emitChange(); - }, - _teamBadRequest: function(err) { - this.STATUS = STATUS.TEAM_BAD_REQUEST; - this.errorDetails = err; - this.emitChange(); - }, - _teamUnauthorized: function(err) { - this.STATUS = STATUS.TEAM_UNAUTHORIZED; - this.errorDetails = err; - this.emitChange(); - }, - _isTeamReadOnly: function(flag) { - this.teamReadOnly = flag; - this.emitChange(); - }, - _updateTeamError: function(err) { - this.STATUS = STATUS.UPDATE_TEAM_ERROR; - if (err.response) { - var errResp = err.response; - if (errResp.badRequest) { - this.errorDetails = err; - } else if (errResp.unauthorized || errResp.forbidden) { - this.errorDetails = {detail: 'You are not permitted to edit this team.'}; - } else { - this.errorDetails = {detail: 'Error updating team. Check if name is between 3 and 30 characters with no spaces.'}; - } - } - this.emitChange(); - }, - _updateTeamSuccess: function(err) { - this.STATUS = STATUS.UPDATE_TEAM_SUCCESS; - this.success = 'Team successfully updated.'; - setTimeout(this._clearErrorStates.bind(this), 5000); - this.emitChange(); - }, - _clearErrorStates: function() { - this.errorDetails = {detail: ''}; - this.success = ''; - this.STATUS = STATUS.DEFAULT; - this.emitChange(); - }, - getState() { - return { - teams: this.teams, - count: this.count, - teamReadOnly: this.teamReadOnly, - success: this.success, - errorDetails: this.errorDetails - }; - }, - dehydrate: function() { - return this.getState(); - }, - rehydrate: function(state) { - this.teams = state.teams; - this.teamReadOnly = state.teamReadOnly; - this.count = state.count; - this.success = state.success; - this.errorDetails = state.errorDetails; - } -}); - -module.exports = DashboardTeamsStore; diff --git a/app/scripts/stores/DeletePipelineStore.js b/app/scripts/stores/DeletePipelineStore.js deleted file mode 100644 index ef0681321e..0000000000 --- a/app/scripts/stores/DeletePipelineStore.js +++ /dev/null @@ -1,46 +0,0 @@ -'use strict'; - -var createStore = require('fluxible/addons/createStore'); -import { - ATTEMPTING, - DEFAULT, - FACEPALM, - SUCCESSFUL -} from './deletepipelinestore/Constants'; - -var debug = require('debug')('SignupStore'); - -export default createStore({ - storeName: 'DeletePipelineStore', - handlers: { - DELETE_PIPELINE_ATTEMPTING: '_start', - DELETE_PIPELINE_FACEPALM: '_facepalm', - DELETE_PIPELINE_SUCCESS: '_success' - }, - initialize() { - this.STATUS = DEFAULT; - }, - _start() { - this.STATUS = ATTEMPTING; - this.emitChange(); - }, - _facepalm() { - this.STATUS = FACEPALM; - this.emitChange(); - }, - _success() { - this.STATUS = SUCCESSFUL; - this.emitChange(); - }, - getState() { - return { - STATUS: this.STATUS - }; - }, - dehydrate() { - return {}; - }, - rehydrate(state) { - this.state = state; - } -}); diff --git a/app/scripts/stores/DeleteRepoFormStore.js b/app/scripts/stores/DeleteRepoFormStore.js deleted file mode 100644 index 21a60d3d33..0000000000 --- a/app/scripts/stores/DeleteRepoFormStore.js +++ /dev/null @@ -1,75 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -import { STATUS } from './deleterepostore/Constants.js'; -const debug = require('debug')('DeleteRepoFormStore'); - -var DeleteRepoFormStore = createStore({ - storeName: 'DeleteRepoFormStore', - handlers: { - DELETE_REPO_ATTEMPT_START: '_deleteRepoAttemptStart', - DELETE_REPO_BAD_REQUEST: '_deleteRepoBadRequest', - DELETE_REPO_ERROR: '_deleteRepoError', - DELETE_REPO_UPDATE_FIELD_WITH_VALUE: '_updateFieldWithValue', - RECEIVE_REPOSITORY: '_receiveRepository', - TOGGLE_DELETE_REPO_NAME_CONFIRM_BOX: '_toggleConfirmBox' - }, - initialize: function() { - this.error = ''; - this.STATUS = STATUS.DEFAULT; - this.values = { - confirmRepoName: '' - }; - }, - _deleteRepoAttemptStart: function() { - this.STATUS = STATUS.ATTEMPTING; - this.emitChange(); - }, - _deleteRepoBadRequest: function(res) { - this.STATUS = STATUS.FORM_ERROR; - this.error = res.detail ? res.detail - : 'Error deleting repository. Please verify if you have permissions.'; - this.emitChange(); - }, - _deleteRepoError: function() { - this.STATUS = STATUS.FORM_ERROR; - this.error = 'Error deleting repository. Please verify if you have permissions.'; - this.emitChange(); - }, - _receiveRepository: function() { - this.initialize(); - this.emitChange(); - }, - _toggleConfirmBox: function() { - if (this.STATUS === STATUS.DEFAULT) { - this.STATUS = STATUS.SHOWING_CONFIRM_BOX; - } else { - this.STATUS = STATUS.DEFAULT; - } - this.error = ''; - this.values.confirmRepoName = ''; - this.emitChange(); - }, - _updateFieldWithValue: function({fieldKey, fieldValue}){ - this.values[fieldKey] = fieldValue; - this.error = ''; - this.emitChange(); - }, - getState: function() { - return { - error: this.error, - STATUS: this.STATUS, - values: this.values - }; - }, - rehydrate: function(state) { - this.error = state.error; - this.STATUS = state.STATUS; - this.values = state.values; - }, - dehydrate: function() { - return this.getState(); - } -}); - -module.exports = DeleteRepoFormStore; diff --git a/app/scripts/stores/EmailNotifStore.js b/app/scripts/stores/EmailNotifStore.js deleted file mode 100644 index 4ada6a99f9..0000000000 --- a/app/scripts/stores/EmailNotifStore.js +++ /dev/null @@ -1,128 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -import _ from 'lodash'; -import { STATUS } from './common/Constants'; -var debug = require('debug')('EmailNotifStore:'); - - -export default createStore({ - storeName: 'EmailNotifStore', - handlers: { - RECEIVE_NOTIFICATIONS: '_receiveNotifications', - NOTIF_CHECKBOX_CLICK: '_updateNotifications', - RESET_EMAIL_NOTIFICATIONS_STORE: '_resetBlankSlate', - SAVE_NOTIFICATIONS_ERROR: '_saveNotifError', - SAVE_NOTIFICATIONS_SUCCESS: '_saveNotifSuccess' - }, - initialize: function() { - // initialize with data from db - this.starNotification = false; - this.imgCommentNotification = false; - this.autoBuildNotification = false; - this.starNotificationID = -1; - this.imgCommentNotificationID = -1; - this.autoBuildNotificationID = -1; - this.STATUS = STATUS.DEFAULT; - this.blankNotificationSlate = {}; - }, - _receiveNotifications: function(notifications) { - for (var i = 0; i < notifications.length; ++i) { - switch(notifications[i].notification) { - case 'new_repo_comment': - this.imgCommentNotification = true; - this.imgCommentNotificationID = notifications[i].id; - break; - case 'new_repo_star': - this.starNotification = true; - this.starNotificationID = notifications[i].id; - break; - case 'trusted_build_fail': - this.autoBuildNotification = true; - this.autoBuildNotificationID = notifications[i].id; - break; - } - } - this.blankNotificationSlate = this.getState(); - debug(this.blankNotificationSlate); - this.attempting = false; - this.emitChange(); - }, - _resetBlankSlate: function() { - var slate = this.blankNotificationSlate; - debug('RESET EMAIL NOTIF BLANK SLATE'); - this.starNotification = slate.starNotification; - this.imgCommentNotification = slate.imgCommentNotification; - this.autoBuildNotification = slate.autoBuildNotification; - this.starNotificationID = slate.starNotificationID; - this.imgCommentNotificationID = slate.imgCommentNotificationID; - this.autoBuildNotificationID = slate.autoBuildNotificationID; - this.STATUS = STATUS.DEFAULT; - this.emitChange(); - }, - _updateNotifications: function(cboxType) { - this.STATUS = STATUS.DEFAULT; - switch(cboxType) { - case 'starNotification': - this.starNotification = !this.starNotification; - break; - case 'imgCommentNotification': - this.imgCommentNotification = !this.imgCommentNotification; - break; - case 'autoBuildNotification': - this.autoBuildNotification = !this.autoBuildNotification; - break; - } - this.emitChange(); - }, - _saveNotifError: function() { - this.STATUS = 'ERROR'; - this.emitChange(); - }, - _saveNotifSuccess: function() { - this.STATUS = STATUS.SUCCESSFUL; - this.emitChange(); - }, - hasChanged: function(type) { - switch (type) { - case 'auto': - return (this.autoBuildNotification !== this.blankNotificationSlate.autoBuildNotification); - case 'star': - return (this.starNotification !== this.blankNotificationSlate.starNotificationID); - case 'comment': - return (this.imgCommentNotification !== this.blankNotificationSlate.imgCommentNotificationID); - default: - break; - } - }, - getAttempt: function() { - return this.attempting; - }, - setAttempt: function(flag) { - this.attempting = flag; - }, - getState: function() { - return { - starNotification: this.starNotification, - imgCommentNotification: this.imgCommentNotification, - autoBuildNotification: this.autoBuildNotification, - starNotificationID: this.starNotificationID, - imgCommentNotificationID: this.imgCommentNotificationID, - autoBuildNotificationID: this.autoBuildNotificationID, - STATUS: this.STATUS - }; - }, - dehydrate: function() { - return _.merge({}, this.getState(), {blankNotificationSlate: this.blankNotificationSlate}); - }, - rehydrate: function(state) { - this.starNotification = state.starNotification; - this.imgCommentNotification = state.imgCommentNotification; - this.autoBuildNotification = state.autoBuildNotification; - this.starNotificationID = state.starNotificationID; - this.imgCommentNotificationID = state.imgCommentNotificationID; - this.autoBuildNotificationID = state.autoBuildNotificationID; - this.STATUS = state.STATUS; - this.blankNotificationSlate = state.blankNotificationSlate; - } -}); diff --git a/app/scripts/stores/EmailsStore.js b/app/scripts/stores/EmailsStore.js deleted file mode 100644 index d48589a878..0000000000 --- a/app/scripts/stores/EmailsStore.js +++ /dev/null @@ -1,155 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -import merge from 'lodash/object/merge'; -import has from 'lodash/object/has'; -import find from 'lodash/collection/find'; -import cloneDeep from 'lodash/lang/cloneDeep'; -import { STATUS, EMAILSTATUS } from './emailsstore/Constants'; - -var debug = require('debug')('EmailsStore'); - -var EmailsStore = createStore({ - storeName: 'EmailsStore', - handlers: { - RECEIVE_EMAILS: '_receiveEmails', - CHANGE_ROUTE: '_resetState', - ADD_EMAIL_INVALID: '_addEmailInvalid', - ADD_EMAIL_SUCCESS: '_addEmailSuccess', - START_SAVE_ACTION: '_startSaveAction', - FINISH_SAVE_ACTION: '_finishSaveAction', - RESEND_EMAIL_CONFIRMATION_ATTEMPT_START: '_resendEmailConfirmationAttemptStart', - RESEND_EMAIL_CONFIRMATION_SENT: '_resendEmailConfirmationSent', - RESEND_EMAIL_CONFIRMATION_FAILED: '_resendEmailConfirmationFail', - RESEND_EMAIL_CONFIRMATION_CLEAR: '_resendClear', - UPDATE_ADD_EMAIL: '_updateAddEmail' - }, - initialize: function() { - this.STATUS = STATUS.DEFAULT; - - this._cleanSlate = { - emails: [] - }; - this.emails = []; - this.emailConfirmations = {}; - this.addEmail = ''; - this.addError = ''; - }, - _startSaveAction() { - this.STATUS = STATUS.SAVING; - this.emitChange(); - }, - _finishSaveAction() { - this.STATUS = STATUS.DEFAULT; - this.emitChange(); - }, - _resendEmailConfirmationAttemptStart(emailID) { - debug('RESEND CONFIRMATION START'); - this.emailConfirmations = merge(this.emailConfirmations, { - [emailID]: EMAILSTATUS.ATTEMPTING - }); - this.emitChange(); - }, - _resendEmailConfirmationSent(emailID) { - debug('RESEND CONFIRMATION SENT'); - this.emailConfirmations = merge(this.emailConfirmations, { - [emailID]: EMAILSTATUS.SUCCESS - }); - this.emitChange(); - }, - _resendEmailConfirmationFail(emailID) { - debug('RESEND CONFIRMATION FAIL'); - this.emailConfirmations = merge(this.emailConfirmations, { - [emailID]: EMAILSTATUS.FAILED - }); - this.emitChange(); - }, - _resendClear(emailID) { - debug('RESEND CONFIRMATION CLEAR'); - this.emailConfirmations = merge(this.emailConfirmations, { - [emailID]: '' - }); - this.emitChange(); - }, - _receiveEmails: function(payload) { - debug(payload); - this.initialize(); - this._cleanSlate = { - /** - * We cloneDeep here because otherwise this.emails - * and this._cleanSlate.emails will refer to the - * same array causing unintuitive behavior. - */ - emails: cloneDeep(payload.emails) - }; - this.emails = payload.emails; - this.emitChange(); - }, - _addEmailInvalid(error) { - this.addError = error[0]; - this.emitChange(); - }, - _addEmailSuccess() { - this.addEmail = ''; - this.emitChange(); - }, - _resetState() { - var {emails} = this._cleanSlate; - this.emails = emails.slice(); - this.addError = ''; - this.emitChange(); - }, - _updateAddEmail(email) { - this.addEmail = email; - this.emitChange(); - }, - isCleanSlatePrimaryEmail: function(email: string) { - debug('cleanSlate.emails', this._cleanSlate.emails, email); - /** - * A function that answers "is this email address a primary email - * address?" with respect to the database, not with respect - * to the state of the client side application - */ - var primaryEmail = find(this._cleanSlate.emails, function(obj) { - return obj.email === email && obj.primary === true; - }); - - debug('primaryEmail', !!primaryEmail); - return !!primaryEmail; - }, - getCleanSlatePrimaryEmailID() { - return find(this._cleanSlate.emails, function(obj) { - return obj.primary === true; - }).id; - }, - getEmails: function() { - return { - emails: this.emails - }; - }, - getState: function() { - return { - STATUS: this.STATUS, - emails: this.emails, - addEmail: this.addEmail, - addError: this.addError, - emailConfirmations: this.emailConfirmations - }; - }, - dehydrate() { - return merge({}, - this.getState(), - { - _cleanSlate: this._cleanSlate - }); - }, - rehydrate(state) { - this._cleanSlate = state._cleanSlate; - this.addEmail = state.addEmail; - this.emails = state.emails.slice(0); - this.emailConfirmations = state.emailConfirmations; - this.addError = state.addError; - } -}); - -module.exports = EmailsStore; diff --git a/app/scripts/stores/EnterprisePaidFormStore.js b/app/scripts/stores/EnterprisePaidFormStore.js deleted file mode 100644 index f77def90e6..0000000000 --- a/app/scripts/stores/EnterprisePaidFormStore.js +++ /dev/null @@ -1,294 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -import { STATUS } from './common/Constants'; -var debug = require('debug')('EnterprisePaidFormStore'); -import each from 'lodash/collection/each'; -import includes from 'lodash/collection/includes'; -import merge from 'lodash/object/merge'; -import keys from 'lodash/object/keys'; -import has from 'lodash/object/has'; -import mapValues from 'lodash/object/mapValues'; -import isString from 'lodash/lang/isString'; - -var noErrorObj = { - hasError: false, - error: '' -}; - -export default createStore({ - storeName: 'EnterprisePaidFormStore', - handlers: { - ENTERPRISE_PAID_RECEIVE_ORGS: '_receiveOrgs', - ENTERPRISE_PAID_CLEAR_FORM: '_clearStore', - ENTERPRISE_PAID_UPDATE_FIELD_WITH_VALUE: '_updateFieldWithValue', - - ENTERPRISE_PAID_ATTEMPT_START: '_enterprisePaidAttemptStart', - ENTERPRISE_PAID_BAD_REQUEST: '_badRequest', - ENTERPRISE_PAID_SUCCESS: '_signupSuccess', - ENTERPRISE_PAID_FACEPALM: '_facepalm', - - BILLING_SUBMIT_START: '_enterprisePaidAttemptStart', - BILLING_SUBMIT_SUCCESS: '_signupSuccess', - BILLING_SUBMIT_ERROR: '_badRequest', - - GET_RECURLY_ERROR: '_updateRecurlyErrors', - ENTERPRISE_PAID_GET_RECURLY_ERROR: 'recurlyError', - ENTERPRISE_PAID_API_ERROR: '_apiError', - ENTERPRISE_PAID_ERRORS: '_validateErrors', - ENTERPRISE_PAID_POPULATE_FORM: '_populateForm' - }, - initialize() { - this.STATUS = STATUS.DEFAULT; - - this.globalFormError = ''; - this.orgs = []; - - this.fields = { - first_name: {}, - last_name: {}, - postal_code: {}, - number: {}, - month: {}, - year: {}, - cvv: {}, - address1: {}, - city: {}, - state: {}, - country: {}, - expiry: {}, - email: {} - }; - - this.values = { - first_name: '', - last_name: '', - postal_code: '', - number: '', - month: '01', - year: '2015', - cvv: '', - address1: '', - city: '', - state: '', - country: 'US', - last_four: '', - card_type: '', - account_first: '', - account_last: '', - company_name: '', - email: '' - }; - }, - _clearStore(){ - this.initialize(); - this.emitChange(); - }, - _populateForm({ - first_name, - last_name, - zip, - month, - year, - address1, - address2, - city, - state, - country, - last_four, - card_type, - account_first, - account_last, - company_name, - email - }) { - var D = new Date(); - var defaultMonth = D.getMonth(); - var defaultYear = D.getFullYear() + 1; - var defaultCountry = 'US'; - this.fields = { - first_name: {}, - last_name: {}, - postal_code: {}, - number: {}, - month: {}, - year: {}, - cvv: {}, - address1: {}, - address2: {}, - city: {}, - state: {}, - country: {}, - expiry: {}, - email: {} - }; - this.values = { - first_name, - last_name, - postal_code: zip, - month: month || defaultMonth, - year: year || defaultYear, - address1, - address2, - city, - state, - country: country || defaultCountry, - last_four, - card_type, - account_first, - account_last, - company_name, - email - }; - this.STATUS = STATUS.DEFAULT; - this.globalFormError = ''; - this.emitChange(); - }, - _updateRecurlyErrors(error) { - const errorFields = error.fields; - debug('Recurly Form errors', errorFields); - let fieldErrors = { - number: { - hasError: includes(errorFields, 'number'), - error: 'There was an error processing your card' - }, - expiry: { - hasError: includes(errorFields, 'month') || includes(errorFields, 'year'), - error: 'This field is invalid' - }, - cvv: { - hasError: includes(errorFields, 'cvv'), - error: 'This field is invalid' - }, - first_name: { - hasError: includes(errorFields, 'first_name'), - error: 'This field is required' - }, - last_name: { - hasError: includes(errorFields, 'last_name'), - error: 'This field is required' - }, - postal_code: { - hasError: includes(errorFields, 'postal_code'), - error: 'This field is invalid' - } - }; - merge(this.fields, fieldErrors); - this.STATUS = STATUS.DEFAULT; - this.globalFormError = error.message; - this.emitChange(); - }, - _facepalm() { - // this happens if things are screwed and we can't recover gracefully - this.STATUS = STATUS.FACEPALM; - this.emitChange(); - }, - recurlyError(fields) { - this.STATUS = STATUS.DEFAULT; - var emitChange = false; - each(fields, function(val, idx) { - if(includes(keys(this.fields), val)) { - emitChange = true; - this.fields[val] = { - hasError: true, - error: 'This field is required' - }; - } - }, this); - - if(emitChange) { - this.emitChange(); - } - }, - _validateErrors(hasError) { - each(hasError, (v, k) => { - if (v) { - if (includes(['number', 'cvv', 'month', 'year', 'country'], k)) { - this.fields[k] = { - hasError: true, - error: 'Invalid ' + k - }; - } else { - this.fields[k] = { - hasError: true, - error: 'Required' - }; - } - } - }); - this.emitChange(); - }, - _updateFieldWithValue({fieldKey, fieldValue}) { - debug(fieldKey, fieldValue); - this.fields[fieldKey] = {hasError: false, error: ''}; - if (includes(['month', 'year'], fieldKey)) { - this.fields.expiry = {hasError: false, error: ''}; - } - if (fieldKey === 'number') { - let card_type = window.recurly.validate.cardType(fieldValue); - this.values.card_type = card_type; - } - this.values[fieldKey] = fieldValue; - this.emitChange(); - }, - _signupSuccess() { - this.STATUS = STATUS.SUCCESSFUL; - this.emitChange(); - }, - _receiveOrgs(namespaces) { - this.orgs = namespaces; - this.emitChange(); - }, - _apiError() { - this.STATUS = STATUS.FACEPALM; - this.emitChange(); - }, - _enterprisePaidAttemptStart() { - this.STATUS = STATUS.ATTEMPTING; - this.emitChange(); - }, - _badRequest(obj) { - this.STATUS = STATUS.ERROR; - - // cycle through the possible form fields - this.fields = mapValues(this.fields, function (errorObject, key) { - if(has(obj, key)) { - return { - hasError: !!obj[key], - error: obj[key][0] - }; - } else { - return errorObject; - } - }); - - if(has(obj, 'non_field_errors')) { - this.globalFormError = obj.non_field_errors[0]; - } else if (has(obj, 'detail')) { - this.globalFormError = obj.detail; - } else if (isString(obj)) { - this.globalFormError = obj; - } - - this.emitChange(); - }, - getState() { - return { - fields: this.fields, - values: this.values, - STATUS: this.STATUS, - orgs: this.orgs, - globalFormError: this.globalFormError - }; - }, - dehydrate() { - return this.getState(); - }, - rehydrate(state) { - this.orgs = state.orgs; - this.values = state.values; - this.fields = state.fields; - this.STATUS = state.STATUS; - this.globalFormError = this.globalFormError; - } -}); diff --git a/app/scripts/stores/EnterprisePartnerTrackingStore.js b/app/scripts/stores/EnterprisePartnerTrackingStore.js deleted file mode 100644 index 6c5afaea8b..0000000000 --- a/app/scripts/stores/EnterprisePartnerTrackingStore.js +++ /dev/null @@ -1,29 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -var debug = require('debug')('EnterprisePartnerTrackingStore'); - -export default createStore({ - storeName: 'EnterprisePartnerTrackingStore', - handlers: { - ENTERPRISE_PARTNER_RECEIVE_CODE: '_receivePartnerTrackingCode' - }, - initialize() { - this.partnervalue = ''; - }, - _receivePartnerTrackingCode({ code }) { - this.partnervalue = code; - this.emitChange(); - }, - getState() { - return { - partnervalue: this.partnervalue - }; - }, - dehydrate() { - return this.getState(); - }, - rehydrate(state) { - this.partnervalue = state.partnervalue; - } -}); diff --git a/app/scripts/stores/EnterpriseTrialFormStore.js b/app/scripts/stores/EnterpriseTrialFormStore.js deleted file mode 100644 index e967f84876..0000000000 --- a/app/scripts/stores/EnterpriseTrialFormStore.js +++ /dev/null @@ -1,140 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -import { ATTEMPTING, DEFAULT, FACEPALM, SUCCESSFUL_SIGNUP } from 'stores/enterprisetrialstore/Constants'; -var debug = require('debug')('EnterpriseTrialFormStore'); -var _ = require('lodash'); - -var noErrorObj = { - hasError: false, - error: '' -}; - -export default createStore({ - storeName: 'EnterpriseTrialFormStore', - handlers: { - ENTERPRISE_TRIAL_RECEIVE_ORGS: '_receiveOrgs', - ENTERPRISE_TRIAL_CLEAR_FORM: '_clearForm', - ENTERPRISE_TRIAL_UPDATE_FIELD_WITH_VALUE: '_updateFieldWithValue', - ENTERPRISE_TRIAL_ATTEMPT_START: '_attemptStart', - ENTERPRISE_TRIAL_BAD_REQUEST: '_badRequest', - ENTERPRISE_TRIAL_SUCCESS: '_signupSuccess', - ENTERPRISE_TRIAL_FACEPALM: '_facepalm', - CREATED_ORGANIZATION: '_clearForm' - }, - initialize() { - this.STATUS = DEFAULT; - this.orgs = []; - this.globalFormError = ''; - - this.fields = { - firstName: {}, - lastName: {}, - companyName: {}, - jobFunction: {}, - email: {}, - phoneNumber: {}, - country: {}, - state: {}, - namespace: {} - }; - - this.values = { - namespace: '', - firstName: '', - lastName: '', - jobFunction: '', - companyName: '', - email: '', - phoneNumber: '', - country: 'US', - state: '' - }; - }, - _facepalm() { - // this happens if things are screwed and we can't recover gracefully - this.STATUS = FACEPALM; - this.globalFormError = 'Something went wrong on the server. We have been alerted to this issue'; - this.emitChange(); - }, - _clearForm() { - this.initialize(); - this.emitChange(); - }, - _clearErrors() { - this.fields = { - firstName: {}, - lastName: {}, - jobFunction: {}, - companyName: {}, - email: {}, - phoneNumber: {}, - country: {}, - state: {}, - namespace: {} - }; - this.globalFormError = ''; - }, - _updateFieldWithValue({fieldKey, fieldValue}) { - this.STATUS = DEFAULT; - this.globalFormError = ''; - this.values[fieldKey] = fieldValue; - this.emitChange(); - }, - _attemptStart() { - this.STATUS = ATTEMPTING; - this.emitChange(); - }, - _signupSuccess() { - this.STATUS = SUCCESSFUL_SIGNUP; - this._clearErrors(); - this.emitChange(); - }, - _receiveOrgs(namespaces) { - this.orgs = namespaces; - //will always have at least current logged in namespace - this.values.namespace = namespaces[0]; - this.emitChange(); - }, - _badRequest(obj) { - this._clearErrors(); - this.STATUS = DEFAULT; - - // cycle through the possible form fields - this.fields = _.mapValues(this.fields, (errorObject, key) => { - if(_.has(obj, key)) { - return { - hasError: !!obj[key], - error: obj[key][0] - }; - } else { - return errorObject; - } - }); - - if(obj && obj.non_field_errors) { - this.globalFormError = obj.non_field_errors[0]; - } - this.emitChange(); - }, - getState() { - return { - fields: this.fields, - values: this.values, - STATUS: this.STATUS, - orgs: this.orgs, - globalFormError: this.globalFormError - }; - }, - dehydrate() { - return this.getState(); - }, - rehydrate(state) { - this.orgs = state.orgs; - this.fields = state.fields; - this.values = state.values; - this.STATUS = state.STATUS; - this.globalFormError = state.globalFormError; - - } -}); diff --git a/app/scripts/stores/EnterpriseTrialSuccessStore.js b/app/scripts/stores/EnterpriseTrialSuccessStore.js deleted file mode 100644 index b68cf015af..0000000000 --- a/app/scripts/stores/EnterpriseTrialSuccessStore.js +++ /dev/null @@ -1,47 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -import { DEFAULT, - ERROR } from 'stores/enterprisetrialsuccessstore/Constants'; -const debug = require('debug')('EnterpriseTrialSuccessStore'); - -export default createStore({ - storeName: 'EnterpriseTrialSuccessStore', - handlers: { - RECEIVE_TRIAL_LICENSE_FACEPALM: '_facepalm', - RECEIVE_TRIAL_LICENSE: '_receiveTrialLicense', - RECEIVE_TRIAL_LICENSE_BAD_REQUEST: '_receiveTrialLicenseBadRequest' - }, - initialize: function() { - this.license = {}; - this.STATUS = DEFAULT; - }, - _facepalm: function(err) { - this.STATUS = ERROR; - debug(err); - this.emitChange(); - }, - _receiveTrialLicense: function(license) { - this.license = license; - this.emitChange(); - }, - _receiveTrialLicenseBadRequest: function(err) { - this.STATUS = ERROR; - debug(err); - this.emitChange(); - }, - getState: function() { - return { - license: this.license, - STATUS: this.STATUS - }; - }, - rehydrate: function(state) { - this.license = state.license; - this.STATUS = state.STATUS; - }, - dehydrate: function() { - return this.getState(); - } -}); - diff --git a/app/scripts/stores/GithubLinkStore.js b/app/scripts/stores/GithubLinkStore.js deleted file mode 100644 index d1858a851b..0000000000 --- a/app/scripts/stores/GithubLinkStore.js +++ /dev/null @@ -1,60 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -var debug = require('debug')('GithubLinkStore'); - -var GithubLinkStore = createStore({ - storeName: 'GithubLinkStore', - handlers: { - RECEIVE_GITHUB_ID: '_receiveID', - GITHUB_ID_ERROR: '_idError', - GITHUB_SECURITY_ERROR: '_githubSecurityError', - GITHUB_ASSOCIATE_ERROR: '_githubAssociateError' - }, - initialize: function() { - this.githubClientID = ''; - this.error = ''; - }, - _receiveID: function(res) { - this.githubClientID = res.client_id; - this.emitChange(); - }, - _idError: function(err) { - debug(err); - }, - _githubAssociateError: function(errorState) { - debug(errorState); - if (errorState.detail) { - this.error = errorState.detail; - } else { - this.error = 'There was an error during the Github account link. Please check that you do not have the same Github account linked to another Docker Hub account.'; - } - this.emitChange(); - setTimeout(this._clearError.bind(this), 5000); - }, - _githubSecurityError: function(errorState) { - debug(errorState); - this.error = 'There was a security error during the github account linking process.'; - this.emitChange(); - setTimeout(this._clearError.bind(this), 5000); - }, - _clearError: function() { - this.error = ''; - this.emitChange(); - }, - getState: function() { - return { - githubClientID: this.githubClientID, - error: this.error - }; - }, - rehydrate: function(state) { - this.githubClientID = state.githubClientID; - this.error = state.error; - }, - dehydrate: function() { - return this.getState(); - } -}); - -module.exports = GithubLinkStore; diff --git a/app/scripts/stores/JWTStore.js b/app/scripts/stores/JWTStore.js deleted file mode 100644 index d7fcd3b368..0000000000 --- a/app/scripts/stores/JWTStore.js +++ /dev/null @@ -1,73 +0,0 @@ -'use strict'; -import createStore from 'fluxible/addons/createStore'; -var debug = require('debug')('stores: JWTStore'); -import cookie from 'cookie'; - -export default createStore({ - storeName: 'JWTStore', - handlers: { - RECEIVE_JWT: '_receiveJWT', - LOGOUT: '_logout', - LOGOUT_ERROR: '_logoutError', - EXPIRED_SIGNATURE: '_setExpiredSignature' - }, - _receiveJWT(jwt) { - this.jwt = jwt; - this.signatureIsExpired = false; - this.emitChange(); - }, - _logoutError(err) { - debug(err + ' Logout did not complete cleanly on the server'); - this._logout(); //we logout on the client side anyway - }, - _logout() { - this.jwt = null; - this.emitChange(); - }, - _logoutWithNotification(){ - debug('Logging out due to invalid Signature'); - this._logout(); - }, - _setExpiredSignature(){ - this.signatureIsExpired = true; - this.jwt = null; - this.emitChange(); - }, - getJWT() { - return this.jwt; - }, - getState() { - return { - jwt: this.jwt, - signatureIsExpired: this.signatureIsExpired - }; - }, - isLoggedIn() { - //Return true if user is logged in - return !!this.jwt; - }, - dehydrate() { - if(this.signatureIsExpired) { - return { - jwt: null, - signatureIsExpired: true - }; - } else { - return { - jwt: this.jwt, - signatureIsExpired: false - }; - } - }, - rehydrate(state) { - debug('rehydrate', state); - if(state.signatureIsExpired) { - debug('signatureIsExpired'); - this._logoutWithNotification(); - } else { - debug('signatureIsValid'); - this.signatureIsExpired = state.signatureIsExpired; - this._receiveJWT(state.jwt); - } - } -}); diff --git a/app/scripts/stores/LoginStore.js b/app/scripts/stores/LoginStore.js deleted file mode 100644 index a074541f06..0000000000 --- a/app/scripts/stores/LoginStore.js +++ /dev/null @@ -1,108 +0,0 @@ -'use strict'; - -import _ from 'lodash'; -import { STATUS } from './loginstore/Constants'; -import createStore from 'fluxible/addons/createStore'; -var debug = require('debug')('LoginStore'); - -export default createStore({ - storeName: 'LoginStore', - handlers: { - LOGIN_ATTEMPT_START: '_loginAttemptStart', - LOGIN_UNAUTHORIZED: '_loginUnauthorized', - LOGIN_UNAUTHORIZED_DETAIL: '_loginUnauthorizedDetail', - LOGIN_BAD_REQUEST: '_badRequest', - LOGIN_ERROR: '_loginError', - LOGIN_UPDATE_FIELD_WITH_VALUE: '_updateFieldWithValue', - LOGIN_CLEAR: '_clearLoginForm' - }, - initialize() { - this.STATUS = STATUS.DEFAULT; - this.globalFormError = ''; - - this.fields = { - username: {}, - password: {} - }; - - this.values = { - username: '', - password: '' - }; - }, - _clearLoginForm() { - debug('Clearing'); - this.initialize(); - this.emitChange(); - }, - _loginAttemptStart() { - this.STATUS = STATUS.ATTEMPTING_LOGIN; - this.emitChange(); - }, - _loginError(err){ - this.STATUS = STATUS.GENERIC_ERROR; - this.globalFormError = 'There was an error contacting the server. Please try again later.'; - this.emitChange(); - }, - _badRequest(obj) { - this.STATUS = STATUS.DEFAULT; - /** - * This function expects keys which match the `this.fields` keys - * with an array of errors: - * - * { - * username: ['this field is required'] - * } - */ - let shouldEmitChange = false; - - // cycle through the possible form fields - this.fields = _.mapValues(this.fields, function (errorObject, key) { - if(_.has(obj, key)) { - shouldEmitChange = true; - return { - hasError: !!obj[key], - error: obj[key][0] - }; - } else { - return errorObject; - } - }); - - if(shouldEmitChange) { - this.emitChange(); - } - }, - _loginUnauthorized() { - this.STATUS = STATUS.ERROR_UNAUTHORIZED; - this.globalFormError = 'Login Failed. The username or password may be incorrect.'; - this.emitChange(); - }, - _loginUnauthorizedDetail({detail}) { - this.STATUS = STATUS.ERROR_UNAUTHORIZED; - this.globalFormError = detail; - this.emitChange(); - }, - getState() { - return { - fields: this.fields, - values: this.values, - STATUS: this.STATUS, - globalFormError: this.globalFormError - }; - }, - _updateFieldWithValue: function({fieldKey, fieldValue}){ - this.fields[fieldKey] = { - hasError: false, - error: '' - }; - this.values[fieldKey] = fieldValue; - this.emitChange(); - }, - dehydrate: function() { - return {}; - }, - rehydrate: function(state) { - this.state = state; - } -}); diff --git a/app/scripts/stores/NotifyStore.js b/app/scripts/stores/NotifyStore.js deleted file mode 100644 index 57c2cc30b5..0000000000 --- a/app/scripts/stores/NotifyStore.js +++ /dev/null @@ -1,44 +0,0 @@ -'use strict'; - -/** - * displays alert-style dismissable notifications to the user - */ - -const createStore = require('fluxible/addons/createStore'); -const debug = require('debug')('NotifyStore'); - -var NotifyStore = createStore({ - storeName: 'NotifyStore', - handlers: { - NEW_ALERT: '_newAlert', - EXPIRE_ALERT: '_expireAlert', - EXPIRED_SIGNATURE: '_newDetailAlert' - }, - initialize: function() { - // alerts have a timestamp-based key - this.alerts = {}; - }, - _newAlert: function(obj) { - this.alerts[+new Date()] = obj.msg; - debug(this.alerts); - this.emitChange(); - }, - _newDetailAlert: function(msg) { - debug(msg); - this._newAlert({ - msg: 'You have been logged out because your token has expired or was invalid' - }); - }, - getState: function() { - return this.state; - }, - dehydrate: function() { - return this.getState(); - }, - rehydrate: function(state) { - debug(state); - this.alerts = state.alerts; - } -}); - -module.exports = NotifyStore; diff --git a/app/scripts/stores/OrgTeamStore.js b/app/scripts/stores/OrgTeamStore.js deleted file mode 100644 index cc8b54ed7f..0000000000 --- a/app/scripts/stores/OrgTeamStore.js +++ /dev/null @@ -1,90 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -import { STATUS } from './orgteamstore/Constants'; - -var OrgTeamStore = createStore({ - storeName: 'OrgTeamStore', - handlers: { - CREATE_ORG_TEAM: '_createOrgTeam', - RECEIVE_ORG_TEAM: '_receiveOrgTeam', - RECEIVE_TEAM_MEMBERS: '_receiveOrgMembers', - TEAM_ERROR: '_orgTeamError', - TEAM_BAD_REQUEST: '_teamBadRequest', - TEAM_UNAUTHORIZED: '_teamUnauthorized', - ORG_TEAM_CLEAR_ERROR_STATES: '_clearErrorStates' - }, - initialize: function() { - // initialize - this.name = ''; - this.description = ''; - this.members = []; - this.errorDetails = {}; - this.success = ''; - this.STATUS = STATUS.DEFAULT; - }, - //TODO: this will be removed once we have API - _createOrgTeam: function(payload) { - this.name = payload.name; - this.description = payload.description; - this.STATUS = STATUS.CREATE_TEAM_SUCCESS; - this.emitChange(); - }, - _receiveOrgTeam: function(orgTeam) { - this.name = orgTeam.name; - this.description = orgTeam.description; - this.emitChange(); - }, - _receiveOrgMembers: function(members) { - this.members = members; - this.emitChange(); - }, - _orgTeamError: function(err) { - this.STATUS = STATUS.TEAM_ERROR; - this.STATUS = STATUS.GENERAL_SERVER_ERROR; - this.errorDetails = {detail: 'Error updating team. Check if name is between 3 and 30 characters with no spaces.'}; - this.emitChange(); - }, - _teamBadRequest: function(err) { - this.STATUS = STATUS.TEAM_BAD_REQUEST; - this.errorDetails = {detail: 'Please check your input values. The team name may already exist or the characters may be invalid.'}; - this.emitChange(); - }, - _teamUnauthorized: function(err) { - this.STATUS = STATUS.TEAM_UNAUTHORIZED; - this.errorDetails = {detail: 'You have no permission to edit this team.'}; - this.emitChange(); - }, - _clearErrorStates: function() { - this.errorDetails = {}; - this.success = ''; - this.STATUS = STATUS.DEFAULT; - this.emitChange(); - }, - getState: function() { - return { - name: this.name, - description: this.description, - members: this.members, - errorDetails: this.errorDetails, - success: this.success, - STATUS: this.STATUS - }; - }, - getMembers: function() { - return this.members; - }, - dehydrate: function() { - return this.getState(); - }, - rehydrate: function(state) { - this.name = state.name; - this.description = state.description; - this.members = state.members; - this.errorDetails = state.errorDetails; - this.success = state.success; - this.STATUS = state.STATUS; - } -}); - -module.exports = OrgTeamStore; diff --git a/app/scripts/stores/OrganizationStore.js b/app/scripts/stores/OrganizationStore.js deleted file mode 100644 index 9b12f12b70..0000000000 --- a/app/scripts/stores/OrganizationStore.js +++ /dev/null @@ -1,130 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -import _ from 'lodash'; - -var OrganizationStore = createStore({ - storeName: 'OrganizationStore', - handlers: { - RECEIVE_ORGANIZATION: '_updateOrg', - CREATED_ORGANIZATION: '_onCreateOrg', - SELECT_ORGANIZATION: '_onCurrentOrgChange', - RECEIVE_ORG_TEAMS: '_receiveOrgTeams', - CURRENT_USER_ORGS: '_onGetCurrentOrgs', - UPDATE_ORG_SUCCESS: '_updateOrgSuccess', - UPDATE_ORG_ERROR: '_updateOrgError' - }, - initialize: function() { - // initialize - this.name = ''; - this.gravatarURL = 'https://secure.gravatar.com/avatar/00000000000000000000000000000000?d=retro&f=y'; - this.currentOrg = {}; - this.orgs = []; - this.currentOrgTeams = []; - this.success = ''; - this.error = ''; - }, - _onCreateOrg: function(payload) { - this.receiveState({ - currentOrg: payload.newOrg, - orgs: payload.userOrgs - }); - this.emitChange(); - }, - _updateOrg: function(payload) { - this.receiveState({ - currentOrg: payload - }); - this.emitChange(); - }, - _onGetCurrentOrgs: function(payload) { - this.receiveState({ - orgs: payload.results - }); - this.emitChange(); - }, - _onCurrentOrgChange: function(payload) { - this.receiveState({ - currentOrg: this.getOrg(payload) - }); - this.emitChange(); - }, - _receiveOrgTeams: function(orgTeams) { - this.receiveState({ - currentOrgTeams: orgTeams.results - }); - this.emitChange(); - }, - _updateOrgSuccess: function() { - this.success = 'Updated Organization Details Successfully!'; - setTimeout(this._clearOrgErrorStates.bind(this), 5000); - this.emitChange(); - }, - _updateOrgError: function(err) { - var errResponse = err.response; - if (errResponse.badRequest) { - _.forIn(errResponse.body, function(v, k) { - this.error += k + ': ' + v.join(',') + '\n'; - }.bind(this)); - } else if(errResponse.unauthorized || errResponse.forbidden) { - this.error = 'You have no permission to edit this organization.'; - } else { - this.error = 'An error occurred during the organization update. Please try again later'; - } - setTimeout(this._clearOrgErrorStates.bind(this), 5000); - this.emitChange(); - }, - _clearOrgErrorStates: function() { - this.success = ''; - this.error = ''; - this.emitChange(); - }, - receiveState: function(payload) { - this.name = payload.orgname || this.name; - this.gravatarURL = payload.gravatar_url || this.gravatarURL; - this.currentOrg = payload.currentOrg || this.currentOrg; - this.currentOrgTeams = payload.currentOrgTeams || this.currentOrgTeams; - this.orgs = payload.orgs || this.orgs; - }, - getState: function() { - return { - name: this.name, - gravatarURL: this.gravatarURL, - currentOrg: this.currentOrg, - currentOrgTeams: this.currentOrgTeams, - orgs: this.orgs, - error: this.error, - success: this.success - }; - }, - getOrgs: function() { - return this.orgs; - }, - getCurrentOrg: function() { - //returns currently selected org - return this.currentOrg; - }, - getOrg: function(name) { - //Assuming org names are unique and expecting filter to return an array of exactly 1 item - return _.filter(this.orgs, function(org) { - return org.orgname === name; - })[0]; - }, - getOrgTeams: function() { - return this.currentOrgTeams; - }, - dehydrate: function() { - return this.getState(); - }, - rehydrate: function(state) { - this.name = state.name; - this.gravatarURL = state.gravatarURL; - this.currentOrg = state.currentOrg; - this.currentOrgTeams = state.currentOrgTeams; - this.orgs = state.orgs; - this.error = state.error; - this.success = state.success; - } -}); - -module.exports = OrganizationStore; diff --git a/app/scripts/stores/OutboundCommunicationStore.js b/app/scripts/stores/OutboundCommunicationStore.js deleted file mode 100644 index 6aa321d62c..0000000000 --- a/app/scripts/stores/OutboundCommunicationStore.js +++ /dev/null @@ -1,90 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -import _ from 'lodash'; -import { STATUS } from './common/Constants'; -var debug = require('debug')('AccountNotifStore:'); - -export default createStore({ - storeName: 'OutboundCommunicationStore', - handlers: { - RECEIVE_EMAIL_SUBSCRIPTIONS: '_receiveEmailSubscriptions', - RESET_OUTBOUND_EMAILS_STORE: '_resetBlankSlate', - SAVE_OUTBOUND_ERROR: '_saveOutboundError', - SAVE_OUTBOUND_SUCCESS: '_saveOutboundSuccess', - UPDATE_OUTBOUND: '_updateOutbound', - UPDATE_BETA_GROUP: '_updateBetaGroup' - }, - initialize: function() { - // initialize with data from db - /*eslint-disable camelcase */ - this.weeklyDigest = { - subscribed_emails: [], - unsubscribed_emails: [] - }; - this.digestEmails = []; - this.betaGroup = { - subscribed_emails: [], - unsubscribed_emails: [] - }; - /*eslint-enable camelcase */ - this.betaEmails = []; - this.STATUS = STATUS.DEFAULT; - this.blankOutboundSlate = {}; - }, - _receiveEmailSubscriptions: function(payload) { - this.weeklyDigest = payload.weeklyDigest; - this.digestEmails = payload.weeklyDigest.subscribed_emails.concat(payload.weeklyDigest.unsubscribed_emails); - this.betaGroup = payload.betaGroup; - this.betaEmails = payload.betaGroup.subscribed_emails.concat(payload.betaGroup.unsubscribed_emails); - this.blankOutboundSlate = this.getState(); - this.emitChange(); - }, - _resetBlankSlate: function() { - var slate = this.blankOutboundSlate; - debug('RESET OUTBOUND BLANK SLATE'); - this.weeklyDigest = slate.weeklyDigest; - this.digestEmails = slate.digestEmails; - this.betaGroup = slate.betaGroup; - this.betaEmails = slate.betaEmails; - this.STATUS = STATUS.DEFAULT; - this.emitChange(); - }, - _updateOutbound: function(newList) { - this.STATUS = STATUS.DEFAULT; - if (newList.list === 'weekly') { - this.weeklyDigest = newList.data; - } else if (newList.list === 'beta') { - this.betaGroup = newList.data; - } - this.emitChange(); - }, - _saveOutboundError: function() { - this.STATUS = 'ERROR'; - this.emitChange(); - }, - _saveOutboundSuccess: function() { - this.STATUS = STATUS.SUCCESSFUL; - this.emitChange(); - }, - getState: function() { - return { - weeklyDigest: this.weeklyDigest, - digestEmails: this.digestEmails, - betaGroup: this.betaGroup, - betaEmails: this.betaEmails, - STATUS: this.STATUS - }; - }, - dehydrate: function() { - return _.merge({}, this.getState(), {blankOutboundSlate: this.blankOutboundSlate}); - }, - rehydrate: function(state) { - this.weeklyDigest = state.weeklyDigest; - this.digestEmails = state.digestEmails; - this.betaGroup = state.betaGroup; - this.betaEmails = state.betaEmails; - this.STATUS = state.STATUS; - this.blankOutboundSlate = state.blankOutboundSlate; - } -}); diff --git a/app/scripts/stores/PipelineHistoryStore.js b/app/scripts/stores/PipelineHistoryStore.js deleted file mode 100644 index 59b9494f2d..0000000000 --- a/app/scripts/stores/PipelineHistoryStore.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -const debug = require('debug')('PipelineHistory'); - -export default createStore({ - storeName: 'PipelineHistoryStore', - handlers: { - RECEIVE_PIPELINE_HISTORY: '_receivePipelineHistory' - }, - initialize() { - this.results = {}; - }, - _receivePipelineHistory(data) { - this.results[data.slug] = {}; - this.results[data.slug].results = data.payload.results; - this.results[data.slug].count = data.payload.count; - this.emitChange(); - }, - getState() { - return { - results: this.results - }; - }, - dehydrate() { - return this.getState(); - }, - rehydrate(state) { - this.results = state.results; - } -}); diff --git a/app/scripts/stores/PlansStore.js b/app/scripts/stores/PlansStore.js deleted file mode 100644 index 8ac12e6c89..0000000000 --- a/app/scripts/stores/PlansStore.js +++ /dev/null @@ -1,74 +0,0 @@ -'use strict'; -import createStore from 'fluxible/addons/createStore'; -var debug = require('debug')('PlansStore'); - -var PlansStore = createStore({ - storeName: 'PlansStore', - handlers: { - RECEIVE_BILLING_PLANS: '_receivePlans', - RECEIVE_BILLING_INFO: '_receiveBilling', - RECEIVE_BILLING_SUBSCRIPTION: '_receiveBillingSubscription', - RESET_CURRENT_PLAN: '_resetCurrentPlan' - }, - initialize: function() { - this.plansList = []; - this.currentPlan = { - plan: '', - package: '', - subscription_uuid: '', - state: '', - add_ons: [] - }; - }, - _clearPlan: function() { - this.currentPlan = { - plan: '', - package: '', - subscription_uuid: '', - state: '', - add_ons: [] - }; - }, - _receiveBilling: function(payload){ - debug('RECEIVE BILLING: ', payload); - this._clearPlan(); - if (payload.currentPlan) { - this.currentPlan = payload.currentPlan; - } - this.emitChange(); - }, - _receiveBillingSubscription: function(payload) { - this._clearPlan(); - if (payload.currentPlan) { - this.currentPlan = payload.currentPlan; - } - this.emitChange(); - }, - _resetCurrentPlan: function(payload) { - this._clearPlan(); - if (payload.currentPlan) { - this.currentPlan = payload.currentPlan; - } - this.emitChange(); - }, - _receivePlans: function(payload) { - debug(payload); - this.plansList = payload.plansList; - this.emitChange(); - }, - getState() { - return { - plansList: this.plansList, - currentPlan: this.currentPlan - }; - }, - dehydrate() { - return this.getState(); - }, - rehydrate(state) { - this.plansList = state.plansList; - this.currentPlan = state.currentPlan; - } -}); - -module.exports = PlansStore; diff --git a/app/scripts/stores/PrivateRepoUsageStore.js b/app/scripts/stores/PrivateRepoUsageStore.js deleted file mode 100644 index ab21e79cc1..0000000000 --- a/app/scripts/stores/PrivateRepoUsageStore.js +++ /dev/null @@ -1,63 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -var debug = require('debug')('PrivateReposUsageStore'); - -var PrivateRepoUsageStore = createStore({ - storeName: 'PrivateRepoUsageStore', - handlers: { - RECEIVE_PRIVATE_REPOSTATS: '_receivePrivateRepoStats', - PRIVATE_REPOSTATS_NO_PERMISSIONS: '_notAvailable' - }, - initialize: function() { - this.privateRepoUsed = 0; - this.numFreePrivateRepos = 0; - this.defaultRepoVisibility = 'public'; - this.privateRepoAvailable = 0; - this.privateRepoPercentUsed = 0; - this.privateRepoLimit = 0; - this.notAvailable = false; - }, - _receivePrivateRepoStats: function(stats) { - this.notAvailable = false; - /*eslint-disable camelcase */ - this.privateRepoUsed = stats.private_repo_used; - this.numFreePrivateRepos = stats.num_free_private_repos; - this.defaultRepoVisibility = stats.default_repo_visibility; - this.privateRepoAvailable = stats.private_repo_available; - this.privateRepoPercentUsed = stats.private_repo_percent_used; - this.privateRepoLimit = stats.private_repo_limit; - /*eslint-enable camelcase */ - this.emitChange(); - }, - _notAvailable: function(err) { - //No permissions to see the private repo stats for this org - this.notAvailable = true; - this.emitChange(); - }, - getState: function() { - return { - privateRepoUsed: this.privateRepoUsed, - numFreePrivateRepos: this.numFreePrivateRepos, - defaultRepoVisibility: this.defaultRepoVisibility, - privateRepoAvailable: this.privateRepoAvailable, - privateRepoPercentUsed: this.privateRepoPercentUsed, - privateRepoLimit: this.privateRepoLimit, - notAvailable: this.notAvailable - }; - }, - dehydrate: function() { - return this.getState(); - }, - rehydrate: function(state) { - this.privateRepoUsed = state.privateRepoUsed; - this.numFreePrivateRepos = state.numFreePrivateRepos; - this.defaultRepoVisibility = state.defaultRepoVisibility; - this.privateRepoAvailable = state.privateRepoAvailable; - this.privateRepoPercentUsed = state.privateRepoPercentUsed; - this.privateRepoLimit = state.privateRepoLimit; - this.notAvailable = state.notAvailable; - } -}); - -module.exports = PrivateRepoUsageStore; diff --git a/app/scripts/stores/RepoDetailsBuildLogs.js b/app/scripts/stores/RepoDetailsBuildLogs.js deleted file mode 100644 index 9d263b87b7..0000000000 --- a/app/scripts/stores/RepoDetailsBuildLogs.js +++ /dev/null @@ -1,29 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -var debug = require('debug')('RepoDetailsBuildLogsStore'); - -export default createStore({ - storeName: 'RepoDetailsBuildLogsStore', - handlers: { - BUILD_LOGS_RECEIVE: '_receiveBuildLogs' - }, - initialize() { - this.build_results = {}; - }, - _receiveBuildLogs(res) { - this.build_results = res.build_results; - this.emitChange(); - }, - getState() { - return { - build_results: this.build_results - }; - }, - rehydrate(state) { - this.build_results = state.build_results; - }, - dehydrate() { - return this.getState(); - } -}); diff --git a/app/scripts/stores/RepoDetailsBuildsStore.js b/app/scripts/stores/RepoDetailsBuildsStore.js deleted file mode 100644 index fbd102343d..0000000000 --- a/app/scripts/stores/RepoDetailsBuildsStore.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -var debug = require('debug')('RepoDetailsBuildsStore'); - -var RepoDetailsBuildsStore = createStore({ - storeName: 'RepoDetailsBuildsStore', - handlers: { - RECEIVE_BUILD_HISTORY_FOR_REPOSITORY: '_receiveBuilds' - }, - initialize() { - this.results = []; - this.count = 0; - }, - _receiveBuilds(res) { - debug('receiving builds', res); - this.results = res.results; - this.count = res.count; - this.emitChange(); - }, - getState: function() { - return { - results: this.results, - count: this.count - }; - }, - rehydrate(state) { - this.results = state.results; - this.count = state.count; - }, - dehydrate() { - return this.getState(); - } -}); - -module.exports = RepoDetailsBuildsStore; diff --git a/app/scripts/stores/RepoDetailsDockerfileStore.js b/app/scripts/stores/RepoDetailsDockerfileStore.js deleted file mode 100644 index ed1a1aee22..0000000000 --- a/app/scripts/stores/RepoDetailsDockerfileStore.js +++ /dev/null @@ -1,32 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -var debug = require('debug')('RepoDetailsDockerfileStore'); - -var RepoDetailsDockerfileStore = createStore({ - storeName: 'RepoDetailsDockerfileStore', - handlers: { - RECEIVE_DOCKERFILE_FOR_REPOSITORY: '_receiveDockerfile' - }, - initialize: function() { - this.dockerfile = ''; - }, - _receiveDockerfile: function(res) { - debug('dockerfile', res); - this.dockerfile = res.contents; - this.emitChange(); - }, - getState: function() { - return { - dockerfile: this.dockerfile - }; - }, - rehydrate: function(state) { - this.dockerfile = state.dockerfile; - }, - dehydrate: function() { - return this.getState(); - } -}); - -module.exports = RepoDetailsDockerfileStore; diff --git a/app/scripts/stores/RepoDetailsLongDescriptionFormStore.js b/app/scripts/stores/RepoDetailsLongDescriptionFormStore.js deleted file mode 100644 index d9ce6e5b60..0000000000 --- a/app/scripts/stores/RepoDetailsLongDescriptionFormStore.js +++ /dev/null @@ -1,116 +0,0 @@ -'use strict'; - -import _ from 'lodash'; -import createStore from 'fluxible/addons/createStore'; -var debug = require('debug')('RepoDetailsLongDescriptionFormStore'); - -export default createStore({ - storeName: 'RepoDetailsLongDescriptionFormStore', - handlers: { - RECEIVE_REPOSITORY: '_receiveRepository', - LONG_DESCRIPTION_ATTEMPT_START: '_longDescriptionAttemptStart', - LONG_DESCRIPTION_SUCCESS: '_longDescriptionSuccess', - DETAILS_UNAUTHORIZED: '_detailsUnauthorized', - DETAILS_UNAUTHORIZED_DETAIL: '_detailsUnauthorizedDetail', - LONG_BAD_REQUEST: '_badRequest', - DETAILS_ERROR: '_detailsError', - LONG_DESCRIPTION_UPDATE_FIELD_WITH_VALUE: '_updateFieldWithValue', - DETAILS_RESET_FORMS: '_detailsResetForms', - TOGGLE_LONG_DESCRIPTION_EDIT: '_toggleEditMode' - }, - initialize: function() { - this.isEditing = false; - this.successfulSave = false; - this.fields = { - longDescription: {} - }; - - this._defaultValues = { - longDescription: '' - }; - - this.values = { - longDescription: '' - }; - }, - _longDescriptionAttemptStart() { - debug('starting long description update'); - }, - _longDescriptionSuccess() { - this.fields.longDescription.success = 'Successfully updated full description.'; - //switch back to viewing mode with green outline - this.successfulSave = true; - this.isEditing = false; - this._defaultValues.longDescription = this.values.longDescription; - //clear the green outline and text on successful save - setTimeout(this._clearFeedbackStates.bind(this), 5000); - setTimeout(this._clearSuccessfulSave.bind(this), 5000); - this.emitChange(); - }, - _receiveRepository(repo) { - this.isEditing = false; - this.values.longDescription = repo.full_description || ''; - this._defaultValues.longDescription = repo.full_description || ''; - this.emitChange(); - }, - _detailsResetForms() { - // reset form value to repo longdescription - this.values.longDescription = this._defaultValues.longDescription; - // reset errors - this.fields.longDescription = {}; - this.emitChange(); - }, - _badRequest(obj) { - this.fields.longDescription.hasError = !!obj.full_description; - this.fields.longDescription.error = obj.full_description[0]; - setTimeout(this._clearFeedbackStates.bind(this), 5000); - this.emitChange(); - }, - _detailsError() { - this.fields.longDescription.hasError = true; - this.fields.longDescription.error = 'Sorry, your long description could not be saved.'; - setTimeout(this._clearFeedbackStates.bind(this), 5000); - this.emitChange(); - }, - _clearFeedbackStates() { - this.fields.longDescription.error = ''; - this.fields.longDescription.hasError = false; - this.fields.longDescription.success = ''; - this.emitChange(); - }, - _clearSuccessfulSave() { - this.successfulSave = false; - this.emitChange(); - }, - _updateFieldWithValue: function({fieldKey, fieldValue}){ - this.values[fieldKey] = fieldValue; - this.emitChange(); - }, - _toggleEditMode( { isEditing }) { - this.isEditing = isEditing; - //if you cancel, clear the old input - this.values.longDescription = this._defaultValues.longDescription; - //in case you recently saved and you now cancel - this._clearSuccessfulSave(); - this.emitChange(); - }, - getState() { - return { - _defaultValues: this._defaultValues, - fields: this.fields, - values: this.values, - isEditing: this.isEditing, - successfulSave: this.successfulSave - }; - }, - dehydrate: function() { - return this.getState(); - }, - rehydrate: function(state) { - this._defaultValues = state._defaultValues; - this.fields = state.fields; - this.values = state.values; - this.isEditing = state.isEditing; - this.successfulSave = state.successfulSave; - } -}); diff --git a/app/scripts/stores/RepoDetailsShortDescriptionFormStore.js b/app/scripts/stores/RepoDetailsShortDescriptionFormStore.js deleted file mode 100644 index 1f573f12cb..0000000000 --- a/app/scripts/stores/RepoDetailsShortDescriptionFormStore.js +++ /dev/null @@ -1,116 +0,0 @@ -'use strict'; - -import _ from 'lodash'; -import createStore from 'fluxible/addons/createStore'; -var debug = require('debug')('RepoDetailsShortDescriptionFormStore'); - -export default createStore({ - storeName: 'RepoDetailsShortDescriptionFormStore', - handlers: { - RECEIVE_REPOSITORY: '_receiveRepository', - SHORT_DESCRIPTION_ATTEMPT_START: '_shortDescriptionAttemptStart', - SHORT_DESCRIPTION_SUCCESS: '_shortDescriptionSuccess', - DETAILS_UNAUTHORIZED: '_detailsUnauthorized', - DETAILS_UNAUTHORIZED_DETAIL: '_detailsUnauthorizedDetail', - SHORT_BAD_REQUEST: '_badRequest', - DETAILS_ERROR: '_detailsError', - SHORT_DESCRIPTION_UPDATE_FIELD_WITH_VALUE: '_updateFieldWithValue', - DETAILS_RESET_FORMS: '_detailsResetForms', - TOGGLE_SHORT_DESCRIPTION_EDIT: '_toggleEditMode' - }, - initialize: function() { - this.isEditing = false; - this.successfulSave = false; - this.fields = { - shortDescription: {} - }; - - this._defaultValues = { - shortDescription: '' - }; - - this.values = { - shortDescription: '' - }; - }, - _shortDescriptionAttemptStart() { - debug('starting short description update'); - }, - _shortDescriptionSuccess() { - this.fields.shortDescription.success = 'Successfully updated short description.'; - //switch back to viewing mode with green outline - this.successfulSave = true; - this.isEditing = false; - this._defaultValues.shortDescription = this.values.shortDescription; - //clear the green outline and text on successful save - setTimeout(this._clearFeedbackStates.bind(this), 5000); - setTimeout(this._clearSuccessfulSave.bind(this), 5000); - this.emitChange(); - }, - _receiveRepository(repo) { - this.isEditing = false; - this.values.shortDescription = repo.description; - this._defaultValues.shortDescription = repo.description; - this.emitChange(); - }, - _detailsResetForms() { - // reset form value to repo shortdescription - this.values.shortDescription = this._defaultValues.shortDescription; - // reset errors - this.fields.shortDescription = {}; - this.emitChange(); - }, - _detailsError() { - this.fields.longDescription.hasError = true; - this.fields.longDescription.error = 'Sorry, your long description could not be saved.'; - setTimeout(this._clearFeedbackStates.bind(this), 5000); - this.emitChange(); - }, - _badRequest(obj) { - this.fields.shortDescription.hasError = true; - this.fields.shortDescription.error = obj.description[0]; - setTimeout(this._clearFeedbackStates.bind(this), 5000); - this.emitChange(); - }, - _clearFeedbackStates() { - this.fields.shortDescription.error = ''; - this.fields.shortDescription.hasError = false; - this.fields.shortDescription.success = ''; - this.emitChange(); - }, - _clearSuccessfulSave() { - this.successfulSave = false; - this.emitChange(); - }, - _updateFieldWithValue: function({fieldKey, fieldValue}){ - this.values[fieldKey] = fieldValue; - this.emitChange(); - }, - _toggleEditMode( { isEditing }) { - this.isEditing = isEditing; - //if you cancel, clear the old input - this.values.shortDescription = this._defaultValues.shortDescription; - //in case you recently saved and you now cancel - this._clearSuccessfulSave(); - this.emitChange(); - }, - getState() { - return { - _defaultValues: this._defaultValues, - fields: this.fields, - values: this.values, - isEditing: this.isEditing, - successfulSave: this.successfulSave - }; - }, - dehydrate: function() { - return this.getState(); - }, - rehydrate: function(state) { - this._defaultValues = state._defaultValues; - this.fields = state.fields; - this.values = state.values; - this.isEditing = state.isEditing; - this.successfulSave = state.successfulSave; - } -}); diff --git a/app/scripts/stores/RepoDetailsVisibilityFormStore.js b/app/scripts/stores/RepoDetailsVisibilityFormStore.js deleted file mode 100644 index 1ef9872139..0000000000 --- a/app/scripts/stores/RepoDetailsVisibilityFormStore.js +++ /dev/null @@ -1,113 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -import { STATUS } from './repovisibilitystore/Constants.js'; -const debug = require('debug')('RepoDetailsVisibilityFormStore'); - -var RepoDetailsVisibilityFormStore = createStore({ - storeName: 'RepoDetailsVisibilityFormStore', - handlers: { - VISIBILITY_BAD_REQUEST: '_badRequest', - VISIBILITY_ERROR: '_visibilityError', - TOGGLE_VISIBILITY_ATTEMPT_START: '_toggleVisibilityAttemptStart', - TOGGLE_VISIBILITY_SUCCESS: '_toggleSuccess', - RECEIVE_PRIVATE_REPOSTATS: '_receivePrivateRepoStats', - RECEIVE_REPOSITORY: '_receiveRepository', - REPO_DETAILS_VISIBILITY_UPDATE_FIELD_WITH_VALUE: '_updateFieldWithValue', - TOGGLE_VISIBILITY_REPO_NAME_CONFIRM_BOX: '_toggleConfirmBox' - }, - initialize: function() { - this.badRequest = ''; - this.error = ''; - this.success = ''; - this.isPrivate = false; - this.privateRepoLimit = null; - this.numPrivateReposAvailable = null; - this.STATUS = STATUS.DEFAULT; - this.values = { - confirmRepoName: '' - }; - }, - _badRequest: function(res) { - this.initialize(); - this.badRequest = res.detail; - this.STATUS = STATUS.FORM_ERROR; - this.emitChange(); - }, - _clearErrors: function () { - this.error = ''; - this.badRequest = ''; - }, - _toggleVisibilityAttemptStart: function() { - this.STATUS = STATUS.ATTEMPTING; - this.emitChange(); - }, - _visibilityError: function(maybeError) { - this.STATUS = STATUS.FORM_ERROR; - if (maybeError) { - this.error = maybeError.detail; - } else { - this.error = 'No private repositories available'; - } - this.emitChange(); - }, - _toggleSuccess: function(isPrivate) { - this.initialize(); - this.isPrivate = isPrivate; - this.emitChange(); - }, - _toggleConfirmBox: function() { - if (this.STATUS === STATUS.DEFAULT) { - this.STATUS = STATUS.SHOWING_CONFIRM_BOX; - } else { - this.STATUS = STATUS.DEFAULT; - } - this._clearErrors(); - this.values.confirmRepoName = ''; - this.emitChange(); - }, - _receivePrivateRepoStats: function(stats) { - /*eslint-disable camelcase */ - this.numPrivateReposAvailable = stats.private_repo_available; - this.privateRepoLimit = stats.private_repo_limit; - /*eslint-enable camelcase */ - this.emitChange(); - }, - _receiveRepository: function(res) { - this.initialize(); - this.isPrivate = res.is_private; - this.emitChange(); - }, - _updateFieldWithValue: function({fieldKey, fieldValue}){ - this.values[fieldKey] = fieldValue; - this._clearErrors(); - this.emitChange(); - }, - getState: function() { - return { - badRequest: this.badRequest, - error: this.error, - success: this.success, - isPrivate: this.isPrivate, - privateRepoLimit: this.privateRepoLimit, - numPrivateReposAvailable: this.numPrivateReposAvailable, - values: this.values, - STATUS: this.STATUS - }; - }, - dehydrate: function() { - return this.getState(); - }, - rehydrate: function(state) { - this.badRequest = state.badRequest; - this.error = state.error; - this.success = state.success; - this.isPrivate = state.isPrivate; - this.numPrivateReposAvailable = state.numPrivateReposAvailable; - this.privateRepoLimit = state.privateRepoLimit; - this.values = state.values; - this.STATUS = state.STATUS; - } -}); - -module.exports = RepoDetailsVisibilityFormStore; diff --git a/app/scripts/stores/RepoSettingsCollaborators.jsx b/app/scripts/stores/RepoSettingsCollaborators.jsx deleted file mode 100644 index 20705e93ea..0000000000 --- a/app/scripts/stores/RepoSettingsCollaborators.jsx +++ /dev/null @@ -1,104 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -import { STATUS } from './collaborators/Constants.js'; -var debug = require('debug')('RepoSettingsCollaborators'); - -export default createStore({ - storeName: 'RepoSettingsCollaborators', - handlers: { - ADD_COLLAB_START: '_addCollabStart', - ADD_COLLAB_ERROR: '_addCollabError', - ADD_COLLAB_SUCCESS: '_addCollabSuccess', - COLLAB_RECEIVE_COLLABORATORS: '_receiveCollaborators', - COLLAB_RECEIVE_TEAMS: '_receiveTeams', - COLLAB_RECEIVE_ALL_TEAMS: '_receiveAllTeams', - DEL_COLLABORATORS_SET_LOADING: 'setLoadingFor', - DEL_COLLABORATORS_SET_ERROR: 'setErrorFor', - DEL_COLLABORATORS_SET_SUCCESS: 'setSuccessFor', - LOGOUT: 'initialize', - ON_ADD_COLLAB_CHANGE: 'onAddCollabChange' - }, - initialize() { - // these are full request objects. Only one will succeed and have a `count` key - this.collaborators = {}; - this.teams = {}; - this.allTeams = {results: []}; - this.newCollaborator = ''; - this.error = ''; - this.requests = {}; - this.STATUS = STATUS.DEFAULT; - }, - getState() { - return { - collaborators: this.collaborators, - teams: this.teams, - allTeams: this.allTeams, - newCollaborator: this.newCollaborator, - error: this.error, - requests: this.requests, - STATUS: this.STATUS - }; - }, - - setLoadingFor(username) { - this.requests[username] = STATUS.ATTEMPTING; - this.emitChange(); - }, - setErrorFor(username) { - this.requests[username] = STATUS.ERROR; - this.emitChange(); - }, - setSuccessFor(username) { - this.requests[username] = STATUS.DEFAULT; - this.newCollaborator = ''; - this.emitChange(); - }, - onAddCollabChange(collaborator) { - this.newCollaborator = collaborator; - this.error = ''; - this.emitChange(); - }, - _addCollabSuccess() { - this.STATUS = STATUS.SUCCESS; - this.newCollaborator = ''; - this.error = ''; - this.emitChange(); - }, - _addCollabError(message) { - this.STATUS = STATUS.ERROR; - this.error = message; - this.emitChange(); - }, - _addCollabStart() { - this.STATUS = STATUS.ATTEMPTING; - this.emitChange(); - }, - _receiveCollaborators(collaborators) { - debug(collaborators); - this.newCollaborator = ''; - this.collaborators = collaborators; - this.emitChange(); - }, - _receiveTeams(teams) { - debug(teams); - this.teams = teams; - this.emitChange(); - }, - _receiveAllTeams(teams) { - this.allTeams = teams; - this.emitChange(); - }, - dehydrate() { - return this.getState(); - }, - rehydrate(state) { - this.collaborators = state.collaborators; - this.teams = state.teams; - this.allTeams = state.allTeams; - this.newCollaborator = state.newCollaborator; - this.error = state.error; - this.requests = state.requests; - this.STATUS = state.STATUS; - } -}); diff --git a/app/scripts/stores/RepositoriesPageStore.js b/app/scripts/stores/RepositoriesPageStore.js deleted file mode 100644 index 9e82aa2480..0000000000 --- a/app/scripts/stores/RepositoriesPageStore.js +++ /dev/null @@ -1,42 +0,0 @@ -'use strict'; - -import createStore from'fluxible/addons/createStore'; - -var ReposStore = createStore({ - storeName: 'RepositoriesPageStore', - handlers: { - RECEIVE_REPOS: '_receiveRepos' - }, - initialize: function() { - this.repos = []; - this.previous = null; - this.next = null; - this.count = null; - }, - _receiveRepos: function(res) { - this.repos = res.results; - this.previous = res.previous; - this.next = res.next; - this.count = res.count; - this.emitChange(); - }, - getState: function() { - return { - repos: this.repos, - previous: this.previous, - next: this.next, - count: this.count - }; - }, - rehydrate: function(state) { - this.repos = state.repos; - this.previous = state.previous; - this.next = state.next; - this.count = state.count; - }, - dehydrate: function() { - return this.getState(); - } -}); - -module.exports = ReposStore; diff --git a/app/scripts/stores/RepositoryCommentsStore.js b/app/scripts/stores/RepositoryCommentsStore.js deleted file mode 100644 index f31d5af4e4..0000000000 --- a/app/scripts/stores/RepositoryCommentsStore.js +++ /dev/null @@ -1,42 +0,0 @@ -'use strict'; -import createStore from 'fluxible/addons/createStore'; -var debug = require('debug')('RepositoryCommentsStore'); - -var RepoCommentsStore = createStore({ - storeName: 'RepositoryCommentsStore', - handlers: { - RECEIVE_REPO_COMMENTS: '_receiveRepoComments' - }, - initialize: function() { - this.results = []; - this.prev = null; - this.next = null; - this.count = 0; - }, - _receiveRepoComments: function(res) { - this.results = res.results; - this.prev = res.previous; - this.next = res.next; - this.count = res.count; - this.emitChange(); - }, - getState: function() { - return { - results: this.results, - prev: this.prev, - next: this.next, - count: this.count - }; - }, - rehydrate: function(state) { - this.results = state.results; - this.prev = state.prev; - this.next = state.next; - this.count = state.count; - }, - dehydrate: function() { - return this.getState(); - } -}); - -module.exports = RepoCommentsStore; diff --git a/app/scripts/stores/RepositoryPageStore.js b/app/scripts/stores/RepositoryPageStore.js deleted file mode 100644 index 64a6866b84..0000000000 --- a/app/scripts/stores/RepositoryPageStore.js +++ /dev/null @@ -1,118 +0,0 @@ -'use strict'; -import createStore from 'fluxible/addons/createStore'; -import _ from 'lodash'; -const STATUS = require('./repostore/Constants').STATUS; -var debug = require('debug')('RepositoryPageStore'); - -var RepoStore = createStore({ - storeName: 'RepositoryPageStore', - handlers: { - RECEIVE_REPOSITORY: '_receiveRepository', - CREATE_REPO_ERROR: '_createRepoError', - TOGGLE_STARRED_STATE: '_toggleStarred', - TOGGLE_VISIBILITY_SUCCESS: '_toggleVisibility', - REPO_NOT_FOUND: '_repoNotFound' - }, - initialize: function() { - this.canEdit = false; - this.description = ''; - this.fullDescription = ''; - this.hasStarred = false; - this.isPrivate = true; - this.isAutomated = false; - this.name = ''; - this.namespace = ''; - this.status = 0; - this.lastUpdated = ''; - this.globalFormError = ''; - this.STATUS = STATUS.DEFAULT; - }, - _createRepoError: function(err) { - if (err) { - var errResponse = err.response.body; - this.globalFormError = ''; - if (!_.isEmpty(errResponse)) { - if (err.response.badRequest) { - this.STATUS = STATUS.BAD_REQUEST; - if (_.has(errResponse, '__all__')) { - this.globalFormError = errResponse.__all__.toString(); - } else if (_.has(errResponse, 'detail')) { - this.globalFormError = errResponse.detail.toString(); - } else { - _.forIn(errResponse, function(v, k) { - this.globalFormError += k + ': ' + v.join(',') + '\n'; - }.bind(this)); - } - } - } else { - this.STATUS = STATUS.GENERAL_SERVER_ERROR; - this.globalFormError = 'An error occurred while creating your repository. Please try again later.'; - } - } - this.emitChange(); - }, - _receiveRepository: function(res) { - debug('receive repo', res); - this.STATUS = STATUS.DEFAULT; - this.canEdit = res.can_edit; - this.description = res.description; - // full_description can come in as null; Default to string - this.fullDescription = res.full_description || ''; - this.hasStarred = res.has_starred; - this.isPrivate = res.is_private; - this.isAutomated = res.is_automated; - this.lastUpdated = res.last_updated; - this.name = res.name; - this.namespace = res.namespace; - this.status = res.status; - - this.emitChange(); - }, - _toggleStarred: function(status) { - this.hasStarred = status; - this.emitChange(); - }, - _toggleVisibility: function(vis) { - this.isPrivate = vis; - this.emitChange(); - }, - _repoNotFound: function(err) { - this.STATUS = STATUS.REPO_NOT_FOUND; - this.emitChange(); - }, - getState: function() { - return { - canEdit: this.canEdit, - description: this.description, - fullDescription: this.fullDescription, - hasStarred: this.hasStarred, - isPrivate: this.isPrivate, - isAutomated: this.isAutomated, - lastUpdated: this.lastUpdated, - name: this.name, - namespace: this.namespace, - status: this.status, - globalFormError: this.globalFormError, - STATUS: this.STATUS - }; - }, - rehydrate: function(state) { - this.canEdit = state.canEdit; - this.description = state.description; - this.fullDescription = state.fullDescription; - this.hasStarred = state.hasStarred; - this.isPrivate = state.isPrivate; - this.isAutomated = state.isAutomated; - this.name = state.name; - this.lastUpdated = state.lastUpdated; - this.namespace = state.namespace; - this.status = state.status; - this.globalFormError = state.globalFormError; - this.STATUS = state.STATUS; - }, - dehydrate: function() { - return this.getState(); - } -}); - -module.exports = RepoStore; diff --git a/app/scripts/stores/SearchStore.js b/app/scripts/stores/SearchStore.js deleted file mode 100644 index 0884946f82..0000000000 --- a/app/scripts/stores/SearchStore.js +++ /dev/null @@ -1,104 +0,0 @@ -'use strict'; -const createStore = require('fluxible/addons/createStore'); -const _ = require('lodash'); -const debug = require('debug')('STORE:SearchStore'); - -//Store to keep track of searches -//TODO: Autocomplete support? -//Query API on general search and return results in a Search Results Component -var SearchStore = createStore({ - storeName: 'SearchStore', - handlers: { - SUBMIT_SEARCH_QUERY: '_submitSearchQuery', - UPDATE_SEARCH_FILTER: '_updateSearchFilter', - UPDATE_SEARCH_SORT: '_updateSearchSort', - UPDATE_SEARCH_PAGE: '_updateSearchPage', - UPDATE_SEARCH_OTHERFILTERS: '_updateSearchFilters', - PROCESS_SEARCH_RESULTS: '_processSearchResults', - SEARCH_ERROR: '_handleSearchError' - }, - initialize: function() { - this.results = ''; - this.queryResult = {}; - this.page = 1; - this.count = 0; - this.next = false; - this.prev = false; - }, - getQueryParams: function() { - //transition to will always have `q` appended as query param at the very least - //Other query params like: `s` -> sort by | `t=User` -> user | `t=Organization` -> Org | `f=official` - // `f=automated_builds` | `s=date_created`, `s=last_updated`, `s=alphabetical`, `s=stars`, `s=downloads` - // `s=pushes` - var queryParams = { - q: this.query || '', - page: this.page || 1, - isOfficial: this.isOfficial || 0, - isAutomated: this.isAutomated || 0, - pullCount: this.pullCount || 0, - starCount: this.starCount || 0 - }; - return queryParams; - }, - _submitSearchQuery: function(payload: string) { - this.query = payload; - this.results = null; - this.emitChange(); - }, - _processSearchResults: function(searchResult) { - this.queryResult = searchResult; - this.count = searchResult.count; - this.results = searchResult.results; - this.next = searchResult.next; - this.prev = searchResult.previous; - this.emitChange(); - }, - _handleSearchError: function(searchError) { - //TODO: Some form of common error handling across all components - debug(searchError); - }, - _updateSearchPage: function(page) { - this.page = page; - this.emitChange(); - }, - _updateSearchFilters: function(params) { - this.isAutomated = params.isAutomated; - this.isOfficial = params.isOfficial; - this.pullCount = params.pullCount; - this.starCount = params.starCount; - this.emitChange(); - }, - getState: function() { - return { - query: this.query, - page: this.page, - queryResult: this.queryResult, - results: this.results, - isOfficial: this.isOfficial, - isAutomated: this.isAutomated, - pullCount: this.pullCount, - starCount: this.starCount, - count: this.count, - next: this.next, - prev: this.prev - }; - }, - dehydrate: function() { - return this.getState(); - }, - rehydrate: function(state) { - this.query = state.query; - this.page = state.page; - this.queryResult = state.queryResult; - this.results = state.results; - this.isOfficial = state.isOfficial; - this.isAutomated = state.isAutomated; - this.pullCount = state.pullCount; - this.starCount = state.starCount; - this.count = state.count; - this.next = state.next; - this.prev = state.prev; - } -}); - -module.exports = SearchStore; diff --git a/app/scripts/stores/SignupStore.js b/app/scripts/stores/SignupStore.js deleted file mode 100644 index bedf00db7f..0000000000 --- a/app/scripts/stores/SignupStore.js +++ /dev/null @@ -1,117 +0,0 @@ -'use strict'; - -var createStore = require('fluxible/addons/createStore'); -import { STATUS } from './signupstore/Constants'; -var debug = require('debug')('SignupStore'); -var _ = require('lodash'); - -var noErrorObj = { - hasError: false, - error: '' -}; - -export default createStore({ - storeName: 'SignupStore', - handlers: { - SIGNUP_CLEAR_FORM: '_signupClearForm', - SIGNUP_CLEAR_PASSWORD: '_signupClearPassword', - SIGNUP_UPDATE_FIELD_WITH_VALUE: '_updateFieldWithValue', - SIGNUP_ATTEMPT_START: '_signupAttemptStart', - SIGNUP_BAD_REQUEST: '_badRequest', - SIGNUP_SUCCESS: '_signupSuccess' - }, - initialize() { - this.STATUS = STATUS.DEFAULT; - - this.fields = { - username: {}, - email: {}, - password: {} - }; - - this.values = { - username: '', - email: '', - password: '' - }; - }, - _signupClearForm() { - this.initialize(); - this.emitChange(); - }, - _signupClearPassword() { - this.values.password = ''; - this.emitChange(); - }, - _updateFieldWithValue({fieldKey, fieldValue}){ - this.values[fieldKey] = fieldValue; - if (fieldValue) { - this.fields[fieldKey] = this._validate({fieldKey, fieldValue}); - } - this.emitChange(); - }, - _signupAttemptStart() { - debug('attempting Signup'); - this.STATUS = STATUS.ATTEMPTING_SIGNUP; - this.emitChange(); - }, - _signupSuccess() { - this.STATUS = STATUS.SUCCESSFUL_SIGNUP; - this.emitChange(); - }, - _badRequest(obj) { - let shouldEmitChange = false; - - // cycle through the possible form fields - _.forEach(_.keys(this.fields), - (key) => { - if(_.has(obj, key)) { - shouldEmitChange = true; - var newField = {}; - newField.hasError = !!obj[key]; - newField.error = obj[key][0]; - this.fields[key] = newField; - } - }); - if(shouldEmitChange) { - this.emitChange(); - } - }, - validations: { - username(value) { - if (value.length < 4){ - return { - hasError: true, - error: 'Username must be at least four characters long' - }; - } else if (!/^[A-Za-z0-9]+$/.test(value)) { - return { - hasError: true, - error: 'Username must contain only letters and digits' - }; - } else { - return noErrorObj; - } - } - }, - _validate({fieldKey, fieldValue}) { - if(_.isFunction(this.validations[fieldKey])) { - return this.validations[fieldKey](fieldValue); - } else { - return noErrorObj; - } - }, - getState() { - return { - fields: this.fields, - values: this.values, - STATUS: this.STATUS - }; - }, - dehydrate() { - return {}; - }, - rehydrate(state) { - this.state = state; - } -}); diff --git a/app/scripts/stores/TriggerBuildStore.js b/app/scripts/stores/TriggerBuildStore.js deleted file mode 100644 index dab896a28a..0000000000 --- a/app/scripts/stores/TriggerBuildStore.js +++ /dev/null @@ -1,50 +0,0 @@ -'use strict'; - -const createStore = require('fluxible/addons/createStore'); -const debug = require('debug')('TriggerBuildStore'); - -var TriggerBuildStore = createStore({ - storeName: 'TriggerBuildStore', - handlers: { - AB_TRIGGER_SUCCESS: '_abTriggerSuccess', - AB_TRIGGER_ERROR: '_abTriggerError' - }, - initialize: function() { - this.abtrigger = { - hasError: false, - success: false - }; - }, - _abTriggerClear: function() { - this.abtrigger = { - hasError: false, - success: false - }; - this.emitChange(); - }, - _abTriggerError: function() { - this.abtrigger.success = false; - this.abtrigger.hasError = true; - setTimeout(this._abTriggerClear.bind(this), 3000); - this.emitChange(); - }, - _abTriggerSuccess: function() { - this.abtrigger.success = true; - this.abtrigger.hasError = false; - setTimeout(this._abTriggerClear.bind(this), 3000); - this.emitChange(); - }, - getState: function() { - return { - abtrigger: this.abtrigger - }; - }, - dehydrate: function() { - return this.getState(); - }, - rehydrate: function(state) { - this.abtrigger = state.abtrigger; - } -}); - -module.exports = TriggerBuildStore; diff --git a/app/scripts/stores/UnlinkAccountsStore.js b/app/scripts/stores/UnlinkAccountsStore.js deleted file mode 100644 index 22f7b2ad35..0000000000 --- a/app/scripts/stores/UnlinkAccountsStore.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -var debug = require('debug')('UnlinkAccountsStore'); - -var BitbucketLinkStore = createStore({ - storeName: 'UnlinkAccountsStore', - handlers: { - GITHUB_UNLINK_ERROR: _unlinkGithubError, - BITBUCKET_UNLINK_ERROR: _unlinkBitbucketError - }, - initialize: function() { - this.error = ''; - }, - _unlinkGithubError: function() { - this.error = 'Error unlinking Github Account. Please try again later'; - this.emitChange(); - }, - _unlinkBitbucketError: function() { - this.error = 'Error unlinking Bitbucket Account. Please try again later'; - this.emitChange(); - }, - getState: function() { - return { - error: this.error - }; - }, - rehydrate: function(state) { - this.error = state.error; - }, - dehydrate: function() { - return this.getState(); - } -}); - -module.exports = UnlinkAccountsStore; diff --git a/app/scripts/stores/UserProfileReposStore.js b/app/scripts/stores/UserProfileReposStore.js deleted file mode 100644 index 397a727c14..0000000000 --- a/app/scripts/stores/UserProfileReposStore.js +++ /dev/null @@ -1,46 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -import filter from 'lodash/collection/filter'; -import { PENDING_DELETE } from 'common/enums/RepoStatus'; -var debug = require('debug')('stores: UserProfileStore'); - -export default createStore({ - storeName: 'UserProfileReposStore', - handlers: { - RECEIVE_PROFILE_REPOS: 'receiveRepos' - }, - initialize() { - this.repos = []; - this.next = null; - this.prev = null; - }, - removePendingDeleteRepos(repos) { - //Remove repos that are in pending delete state from user profile repos - return filter(repos, (repo) => { - const { status } = repo; - return status !== PENDING_DELETE; - }); - }, - receiveRepos(res) { - this.repos = this.removePendingDeleteRepos(res.results); - this.next = res.next; - this.prev = res.previous; - this.emitChange(); - }, - getState() { - return { - repos: this.repos, - next: this.next, - prev: this.prev - }; - }, - dehydrate() { - return this.getState(); - }, - rehydrate(state) { - this.repos = state.repos; - this.next = state.next; - this.prev = state.prev; - } -}); diff --git a/app/scripts/stores/UserProfileStarsStore.js b/app/scripts/stores/UserProfileStarsStore.js deleted file mode 100644 index 1a70b56588..0000000000 --- a/app/scripts/stores/UserProfileStarsStore.js +++ /dev/null @@ -1,37 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -var debug = require('debug')('stores: UserProfileStarsStore'); - -export default createStore({ - storeName: 'UserProfileStarsStore', - handlers: { - RECEIVE_PROFILE_STARRED_REPOS: '_receiveStarredRepos' - }, - initialize() { - this.repos = []; - this.next = null; - this.prev = null; - }, - _receiveStarredRepos(res) { - this.starred = res.results; - this.next = res.next; - this.prev = res.previous; - this.emitChange(); - }, - getState() { - return { - starred: this.starred, - next: this.next, - prev: this.prev - }; - }, - dehydrate() { - return this.getState(); - }, - rehydrate(state) { - this.starred = state.starred; - this.next = state.next; - this.prev = state.prev; - } -}); diff --git a/app/scripts/stores/UserProfileStore.js b/app/scripts/stores/UserProfileStore.js deleted file mode 100644 index a4c44484e7..0000000000 --- a/app/scripts/stores/UserProfileStore.js +++ /dev/null @@ -1,38 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -var debug = require('debug')('UserProfileStore'); - -export default createStore({ - storeName: 'UserProfileStore', - handlers: { - RECEIVE_PROFILE_USER: '_receiveUser', - USER_PROFILE_404: '_fourOHfour' - }, - initialize() { - this.STATUS = 'DEFAULT'; - this.user = {}; - }, - _fourOHfour() { - this.STATUS = '404'; - this.emitChange(); - }, - _receiveUser(user) { - this.STATUS = 'DEFAULT'; - this.user = user; - this.emitChange(); - }, - getState() { - return { - user: this.user, - STATUS: this.STATUS - }; - }, - dehydrate() { - return this.getState(); - }, - rehydrate(state) { - this.user = state.user; - this.STATUS = state.STATUS; - } -}); diff --git a/app/scripts/stores/UserStore.js b/app/scripts/stores/UserStore.js deleted file mode 100644 index ff68d1cfac..0000000000 --- a/app/scripts/stores/UserStore.js +++ /dev/null @@ -1,137 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -import md5 from 'md5'; -var debug = require('debug')('stores: UserStore'); - -var UserStore = createStore({ - storeName: 'UserStore', - handlers: { - RECEIVE_USER: '_receiveUserFromHub', - RECEIVE_NAMESPACES: '_receiveNamespaces', - LOGOUT: '_logout', - EXPIRED_SIGNATURE: '_logout' - }, - initialize: function() { - this.dateJoined = ''; - this.fullName = ''; - this.gravatarEmail = ''; - this.gravatarUrl = ''; - this.isActive = false; - this.isAdmin = false; - this.isStaff = false; - this.profileUrl = ''; - this.company = ''; - this.id = ''; - this.location = ''; - this.userType = 'User'; - this.username = ''; - this.namespaces = []; - }, - _getGravatarUrl: function(email) { - return 'https://secure.gravatar.com/avatar/' + md5( email.trim().toLowerCase() ); - }, - _receiveUserFromHub: function(user) { - - // jscs:disable requireCamelCaseOrUpperCaseIdentifiers - this.dateJoined = user.date_joined; - this.fullName = user.full_name; - this.gravatarEmail = user.gravatar_email; - //TODO: the url has to be handed off from the backend - //This fix should be temporary - this.gravatarUrl = (user.gravatar_url === user.gravatar_email) ? - this._getGravatarUrl(user.gravatar_email) : user.gravatar_url; - this.isActive = user.is_active; - this.isAdmin = user.is_admin; - this.isStaff = user.is_staff; - this.profileUrl = user.profile_url; - // jscs:enable - - this.company = user.company; - this.id = user.id; - this.location = user.location; - this.userType = user.type; - this.username = user.username; - - this.emitChange(); - }, - _receiveNamespaces: function(receivedNamespaces) { - //This is required for creating a repository - //Namespaces are attached to a user, due to permissions/access restrictions - //Eg. { - // "namespaces": [ - // "user", - // "org1", - // "org2" - // ] - //} - this.namespaces = receivedNamespaces.namespaces; - - this.emitChange(); - }, - _logout: function() { - - this.company = ''; - this.dateJoined = ''; - this.fullName = ''; - this.gravatarEmail = ''; - this.gravatarUrl = ''; - this.id = ''; - this.isActive = false; - this.isAdmin = false; - this.isStaff = false; - this.location = ''; - this.profileUrl = ''; - this.userType = 'User'; - this.username = ''; - this.namespaces = []; - - this.emitChange(); - }, - getState: function() { - return { - company: this.company, - dateJoined: this.dateJoined, - fullName: this.fullName, - gravatarEmail: this.gravatarEmail, - gravatarUrl: this.gravatarUrl, - id: this.id, - isActive: this.isActive, - isAdmin: this.isAdmin, - isStaff: this.isStaff, - location: this.location, - profileUrl: this.profileUrl, - userType: this.userType, - username: this.username, - namespaces: this.namespaces - }; - }, - getUsername: function() { - return this.username; - }, - getNamespaces: function() { - return this.namespaces; - }, - dehydrate: function() { - return this.getState(); - }, - rehydrate: function(state) { - debug('rehydrate', state); - this.dateJoined = state.dateJoined; - this.fullName = state.fullName; - this.gravatarEmail = state.gravatarEmail; - this.gravatarUrl = state.gravatarUrl; - this.isActive = state.isActive; - this.isAdmin = state.isAdmin; - this.isStaff = state.isStaff; - this.profileUrl = state.profileUrl; - this.company = state.company; - this.id = state.id; - this.location = state.location; - this.userType = state.userType; - this.username = state.username; - this.namespaces = state.namespaces; - } -}); - -module.exports = UserStore; diff --git a/app/scripts/stores/WebhooksSettingsStore.js b/app/scripts/stores/WebhooksSettingsStore.js deleted file mode 100644 index 8c27103a95..0000000000 --- a/app/scripts/stores/WebhooksSettingsStore.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict'; -import createStore from 'fluxible/addons/createStore'; -const debug = require('debug')('WebhooksSettingsStore'); - -var WebhooksSettingsStore = createStore({ - storeName: 'WebhooksSettingsStore', - handlers: { - RECEIVE_WEBHOOKS: '_receiveWebhooks' - }, - initialize() { - this.pipelines = []; - }, - _receiveWebhooks(payload) { - debug(payload); - this.pipelines = payload.results; - this.emitChange(); - }, - getState() { - return { - pipelines: this.pipelines - }; - }, - dehydrate() { - return this.getState(); - }, - rehydrate(state) { - this.pipelines = state.pipelines; - } -}); - -module.exports = WebhooksSettingsStore; diff --git a/app/scripts/stores/addorganizationstore/Constants.js b/app/scripts/stores/addorganizationstore/Constants.js deleted file mode 100644 index 2da1465eb6..0000000000 --- a/app/scripts/stores/addorganizationstore/Constants.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; -var keyMirror = require('keymirror'); - -// Component-Global form states -var STATUS = keyMirror({ - ATTEMPTING: null, - DEFAULT: null, - FACEPALM: null, - BAD_REQUEST: null, - SUCCESSFUL: null -}); - -module.exports = { - STATUS -}; diff --git a/app/scripts/stores/addtriallicensestore/Constants.js b/app/scripts/stores/addtriallicensestore/Constants.js deleted file mode 100644 index 08e9dfd0ff..0000000000 --- a/app/scripts/stores/addtriallicensestore/Constants.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict'; -import keyMirror from 'keymirror'; - -const STATUS = keyMirror({ - ATTEMPTING_DOWNLOAD: null, - DEFAULT: null, - FACEPALM: null, - SUCCESSFUL_DOWNLOAD: null -}); - -export default STATUS; diff --git a/app/scripts/stores/addwebhookformstore/Constants.js b/app/scripts/stores/addwebhookformstore/Constants.js deleted file mode 100644 index d2ed2ffbf4..0000000000 --- a/app/scripts/stores/addwebhookformstore/Constants.js +++ /dev/null @@ -1,10 +0,0 @@ -'use strict'; -var keyMirror = require('keymirror'); - -export default keyMirror({ - ATTEMPTING: null, - DEFAULT: null, - FACEPALM: null, - SUCCESSFUL: null, - ERROR: null -}); diff --git a/app/scripts/stores/billingformstore/Constants.js b/app/scripts/stores/billingformstore/Constants.js deleted file mode 100644 index 42bb512ddf..0000000000 --- a/app/scripts/stores/billingformstore/Constants.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; -var keyMirror = require('keymirror'); - -// Component-Global form states -var STATUS = keyMirror({ - DEFAULT: null, - ATTEMPTING: null, - SUCCESS: null, - FORM_ERROR: null -}); - -module.exports = { - STATUS -}; diff --git a/app/scripts/stores/collaborators/Constants.js b/app/scripts/stores/collaborators/Constants.js deleted file mode 100644 index 0092c8068c..0000000000 --- a/app/scripts/stores/collaborators/Constants.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; -var keyMirror = require('keymirror'); - -// Component-Global form states -var STATUS = keyMirror({ - DEFAULT: null, - ATTEMPTING: null, - SUCCESS: null, - ERROR: null -}); - -module.exports = { - STATUS -}; diff --git a/app/scripts/stores/common/Constants.js b/app/scripts/stores/common/Constants.js deleted file mode 100644 index aad03f18f9..0000000000 --- a/app/scripts/stores/common/Constants.js +++ /dev/null @@ -1,25 +0,0 @@ -'use strict'; -var keyMirror = require('keymirror'); - -// Component-Global form states -export const STATUS = keyMirror({ - ATTEMPTING: null, - DEFAULT: null, - FACEPALM: null, - SUCCESSFUL: null, - ERROR: null -}); - -export const ACCOUNT = 'account'; -export const BILLING = 'billing'; -export const STRIPE_URL = 'https://api.stripe.com/v1/tokens'; -export const STRIPE_STAGE_TOKEN = 'pk_test_DMJYisAqHlWvFPgRfkKayAcF'; -export const STRIPE_PROD_TOKEN = 'pk_live_89IjovLdwh2MTzV7JsGJK3qk'; -export const BF_STAGE_URL = 'https://api-sandbox.billforward.net:443/v1/tokenization/auth-capture'; -export const BF_PROD_URL = 'https://api.billforward.net/v1/tokenization/auth-capture'; -export const BF_STAGE_TOKEN = 'ec687f76-c1b6-4d71-b919-4fe99202ca13'; -export const BF_PROD_TOKEN = '650cbe35-4aca-4820-a7d1-accec8a7083a'; -export const BILLFORWARD_ACCOUNT_ID = 'billforward-account-id'; -export const v4BillingProfile = (docker_id) => { - return `/api/billing/v4/accounts/${docker_id}/profile`; -}; diff --git a/app/scripts/stores/deletepipelinestore/Constants.js b/app/scripts/stores/deletepipelinestore/Constants.js deleted file mode 100644 index c619b4befb..0000000000 --- a/app/scripts/stores/deletepipelinestore/Constants.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict'; -var keyMirror = require('keymirror'); - -export default keyMirror({ - ATTEMPTING: null, - DEFAULT: null, - FACEPALM: null, - SUCCESSFUL: null -}); diff --git a/app/scripts/stores/deleterepostore/Constants.js b/app/scripts/stores/deleterepostore/Constants.js deleted file mode 100644 index 2282e4de76..0000000000 --- a/app/scripts/stores/deleterepostore/Constants.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; -var keyMirror = require('keymirror'); - -// Component-Global form states -var STATUS = keyMirror({ - ATTEMPTING: null, - DEFAULT: null, - FORM_ERROR: null, - SHOWING_CONFIRM_BOX: null -}); - -module.exports = { - STATUS -}; diff --git a/app/scripts/stores/emailsstore/Constants.js b/app/scripts/stores/emailsstore/Constants.js deleted file mode 100644 index 262d6665c5..0000000000 --- a/app/scripts/stores/emailsstore/Constants.js +++ /dev/null @@ -1,19 +0,0 @@ -'use strict'; -var keyMirror = require('keymirror'); - -// Component-Global form states -var STATUS = keyMirror({ - DEFAULT: null, - SAVING: null -}); - -var EMAILSTATUS = keyMirror({ - SUCCESS: null, - ATTEMPTING: null, - FAILED: null -}); - -module.exports = { - STATUS, - EMAILSTATUS -}; diff --git a/app/scripts/stores/enterprisetrialstore/Constants.js b/app/scripts/stores/enterprisetrialstore/Constants.js deleted file mode 100644 index c1c53dce9c..0000000000 --- a/app/scripts/stores/enterprisetrialstore/Constants.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict'; -import keyMirror from 'keymirror'; - -const STATUS = keyMirror({ - ATTEMPTING: null, - DEFAULT: null, - FACEPALM: null, - SUCCESSFUL_SIGNUP: null -}); - -export default STATUS; diff --git a/app/scripts/stores/enterprisetrialsuccessstore/Constants.js b/app/scripts/stores/enterprisetrialsuccessstore/Constants.js deleted file mode 100644 index 061a46f844..0000000000 --- a/app/scripts/stores/enterprisetrialsuccessstore/Constants.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict'; -import keyMirror from 'keymirror'; - -const STATUS = keyMirror({ - DEFAULT: null, - ERROR: null -}); - -export default STATUS; diff --git a/app/scripts/stores/loginstore/Constants.js b/app/scripts/stores/loginstore/Constants.js deleted file mode 100644 index d8cc11d128..0000000000 --- a/app/scripts/stores/loginstore/Constants.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; -var keyMirror = require('keymirror'); - -// Component-Global form states -var STATUS = keyMirror({ - DEFAULT: null, - ATTEMPTING_LOGIN: null, - ERROR_UNAUTHORIZED: null, - GENERIC_ERROR: null -}); - -module.exports = { - STATUS -}; diff --git a/app/scripts/stores/loginstore/createFormStore.js b/app/scripts/stores/loginstore/createFormStore.js deleted file mode 100644 index cf17dd0cbe..0000000000 --- a/app/scripts/stores/loginstore/createFormStore.js +++ /dev/null @@ -1,88 +0,0 @@ -'use strict'; - -import createStore from 'fluxible/addons/createStore'; -import _ from 'lodash'; -var debug = require('debug')('createFormStore'); -/** - * @param {Array} fields - array of objects with field names - * as keys and inital values as values - * @param {Function} init - old initialize function - */ - -export default function createFormStore(fields, oldSpec) { - - var spec = {}; - - spec.initialize = function() { - this.globalFormError = ''; - _.forOwn(fields, function(key, val){ - this.fields[key] = {}; - this.values[key] = val; - }); - spec.initialize(); - }.bind(spec); - - spec._badRequest = function(obj) { - /** - * obj is an Object with keys that are field names - * and values that are arrays of errors - * - * This function should be used as the handler for - * an HTTP 400 BadRequest - * - * obj = { - * username: ["cannot be empty"] - * } - */ - // did we update state? - var dirty = false; - - _.forOwn(obj, function(key, val) { - if(_.includes(fields, key)) { - this.fields[key].hasError = !!val; - this.fields[key].error = val[0]; - dirty = true; - } - }, this); - - if(dirty) { - this.emitChange(); - } - }; - - spec._getState = function() { - return { - fields: this.fields, - values: this.values, - globalFormError: this.globalFormError - }; - }; - - - spec._updateFieldWithValue = function({fieldKey, fieldValue}){ - this.values[fieldKey] = fieldValue; - this.emitChange(); - }; - - - spec.dehydrate = function() { - return {}; - }, - spec.rehydrate = function(state) { - this.state = state; - }; - - _.merge(spec, oldSpec, function(objectValue, sourceValue, key) { - if(key === 'initializer') { - return sourceValue; - } else if(key === 'getState') { - return function() { - debug('state', this.state); - return _.merge({}, - objectValue.getState(), - sourceValue._getState()); - }; - } - }); - return createStore(spec); -} diff --git a/app/scripts/stores/orgteamstore/Constants.js b/app/scripts/stores/orgteamstore/Constants.js deleted file mode 100644 index 0731e53f0e..0000000000 --- a/app/scripts/stores/orgteamstore/Constants.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; -var keyMirror = require('keymirror'); - -// Component-Global form states -var STATUS = keyMirror({ - DEFAULT: null, - MEMBER_UNAUTHORIZED: null, - TEAM_UNAUTHORIZED: null, - MEMBER_ERROR: null, - TEAM_ERROR: null, - MEMBER_BAD_REQUEST: null, - TEAM_BAD_REQUEST: null, - GENERAL_SERVER_ERROR: null, - CREATE_TEAM_SUCCESS: null, - CREATE_MEMBER_SUCCESS: null, - UPDATE_TEAM_ERROR: null, - UPDATE_TEAM_SUCCESS: null -}); - -module.exports = { - STATUS -}; diff --git a/app/scripts/stores/repodetailstags/Constants.js b/app/scripts/stores/repodetailstags/Constants.js deleted file mode 100644 index 42faf1dbcc..0000000000 --- a/app/scripts/stores/repodetailstags/Constants.js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict'; -var keyMirror = require('keymirror'); - -// Component-Global form states -var STATUS = keyMirror({ - DEFAULT: null, - ERROR: null, - DELETING: null, - CONFIRMING: null -}); - -module.exports = STATUS; diff --git a/app/scripts/stores/repostore/Constants.js b/app/scripts/stores/repostore/Constants.js deleted file mode 100644 index f3faaad35f..0000000000 --- a/app/scripts/stores/repostore/Constants.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; -var keyMirror = require('keymirror'); - -// Component-Global form states -var STATUS = keyMirror({ - DEFAULT: null, - REPO_ALREADY_EXISTS: null, - PRIVATE_REPO_QUOTA_EXCEEDED: null, - BAD_REQUEST: null, - REPO_NOT_FOUND: null -}); - -module.exports = { - STATUS -}; diff --git a/app/scripts/stores/repovisibilitystore/Constants.js b/app/scripts/stores/repovisibilitystore/Constants.js deleted file mode 100644 index 2282e4de76..0000000000 --- a/app/scripts/stores/repovisibilitystore/Constants.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; -var keyMirror = require('keymirror'); - -// Component-Global form states -var STATUS = keyMirror({ - ATTEMPTING: null, - DEFAULT: null, - FORM_ERROR: null, - SHOWING_CONFIRM_BOX: null -}); - -module.exports = { - STATUS -}; diff --git a/app/scripts/stores/signupstore/Constants.js b/app/scripts/stores/signupstore/Constants.js deleted file mode 100644 index 030ee671ac..0000000000 --- a/app/scripts/stores/signupstore/Constants.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict'; -var keyMirror = require('keymirror'); - -// Component-Global form states -var STATUS = keyMirror({ - DEFAULT: null, - ATTEMPTING_SIGNUP: null, - SUCCESSFUL_SIGNUP: null -}); - -module.exports = { - STATUS -}; diff --git a/app/scripts/vendor/Blob.js b/app/scripts/vendor/Blob.js deleted file mode 100644 index 294debb35f..0000000000 --- a/app/scripts/vendor/Blob.js +++ /dev/null @@ -1,215 +0,0 @@ -/* eslint-disable */ -/* Blob.js - * A Blob implementation. - * 2014-07-24 - * - * By Eli Grey, http://eligrey.com - * By Devin Samarin, https://github.com/dsamarin - * License: X11/MIT - * See https://github.com/eligrey/Blob.js/blob/master/LICENSE.md - */ - -/*global self, unescape */ -/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true, - plusplus: true */ - -/*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */ - -if(typeof window !== "undefined") { -(function (view) { - "use strict"; - - view.URL = view.URL || view.webkitURL; - - if (view.Blob && view.URL) { - try { - new Blob; - return; - } catch (e) {} - } - - // Internally we use a BlobBuilder implementation to base Blob off of - // in order to support older browsers that only have BlobBuilder - var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || (function(view) { - var - get_class = function(object) { - return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1]; - } - , FakeBlobBuilder = function BlobBuilder() { - this.data = []; - } - , FakeBlob = function Blob(data, type, encoding) { - this.data = data; - this.size = data.length; - this.type = type; - this.encoding = encoding; - } - , FBB_proto = FakeBlobBuilder.prototype - , FB_proto = FakeBlob.prototype - , FileReaderSync = view.FileReaderSync - , FileException = function(type) { - this.code = this[this.name = type]; - } - , file_ex_codes = ( - "NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR " - + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR" - ).split(" ") - , file_ex_code = file_ex_codes.length - , real_URL = view.URL || view.webkitURL || view - , real_create_object_URL = real_URL.createObjectURL - , real_revoke_object_URL = real_URL.revokeObjectURL - , URL = real_URL - , btoa = view.btoa - , atob = view.atob - - , ArrayBuffer = view.ArrayBuffer - , Uint8Array = view.Uint8Array - - , origin = /^[\w-]+:\/*\[?[\w\.:-]+\]?(?::[0-9]+)?/ - ; - FakeBlob.fake = FB_proto.fake = true; - while (file_ex_code--) { - FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1; - } - // Polyfill URL - if (!real_URL.createObjectURL) { - URL = view.URL = function(uri) { - var - uri_info = document.createElementNS("http://www.w3.org/1999/xhtml", "a") - , uri_origin - ; - uri_info.href = uri; - if (!("origin" in uri_info)) { - if (uri_info.protocol.toLowerCase() === "data:") { - uri_info.origin = null; - } else { - uri_origin = uri.match(origin); - uri_info.origin = uri_origin && uri_origin[1]; - } - } - return uri_info; - }; - } - URL.createObjectURL = function(blob) { - var - type = blob.type - , data_URI_header - ; - if (type === null) { - type = "application/octet-stream"; - } - if (blob instanceof FakeBlob) { - data_URI_header = "data:" + type; - if (blob.encoding === "base64") { - return data_URI_header + ";base64," + blob.data; - } else if (blob.encoding === "URI") { - return data_URI_header + "," + decodeURIComponent(blob.data); - } if (btoa) { - return data_URI_header + ";base64," + btoa(blob.data); - } else { - return data_URI_header + "," + encodeURIComponent(blob.data); - } - } else if (real_create_object_URL) { - return real_create_object_URL.call(real_URL, blob); - } - }; - URL.revokeObjectURL = function(object_URL) { - if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) { - real_revoke_object_URL.call(real_URL, object_URL); - } - }; - FBB_proto.append = function(data/*, endings*/) { - var bb = this.data; - // decode data to a binary string - if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) { - var - str = "" - , buf = new Uint8Array(data) - , i = 0 - , buf_len = buf.length - ; - for (; i < buf_len; i++) { - str += String.fromCharCode(buf[i]); - } - bb.push(str); - } else if (get_class(data) === "Blob" || get_class(data) === "File") { - if (FileReaderSync) { - var fr = new FileReaderSync; - bb.push(fr.readAsBinaryString(data)); - } else { - // async FileReader won't work as BlobBuilder is sync - throw new FileException("NOT_READABLE_ERR"); - } - } else if (data instanceof FakeBlob) { - if (data.encoding === "base64" && atob) { - bb.push(atob(data.data)); - } else if (data.encoding === "URI") { - bb.push(decodeURIComponent(data.data)); - } else if (data.encoding === "raw") { - bb.push(data.data); - } - } else { - if (typeof data !== "string") { - data += ""; // convert unsupported types to strings - } - // decode UTF-16 to binary string - bb.push(unescape(encodeURIComponent(data))); - } - }; - FBB_proto.getBlob = function(type) { - if (!arguments.length) { - type = null; - } - return new FakeBlob(this.data.join(""), type, "raw"); - }; - FBB_proto.toString = function() { - return "[object BlobBuilder]"; - }; - FB_proto.slice = function(start, end, type) { - var args = arguments.length; - if (args < 3) { - type = null; - } - return new FakeBlob( - this.data.slice(start, args > 1 ? end : this.data.length) - , type - , this.encoding - ); - }; - FB_proto.toString = function() { - return "[object Blob]"; - }; - FB_proto.close = function() { - this.size = 0; - delete this.data; - }; - return FakeBlobBuilder; - }(view)); - - view.Blob = function(blobParts, options) { - var type = options ? (options.type || "") : ""; - var builder = new BlobBuilder(); - if (blobParts) { - for (var i = 0, len = blobParts.length; i < len; i++) { - if (Uint8Array && blobParts[i] instanceof Uint8Array) { - builder.append(blobParts[i].buffer); - } - else { - builder.append(blobParts[i]); - } - } - } - var blob = builder.getBlob(type); - if (!blob.slice && blob.webkitSlice) { - blob.slice = blob.webkitSlice; - } - return blob; - }; - - var getPrototypeOf = Object.getPrototypeOf || function(object) { - return object.__proto__; - }; - view.Blob.prototype = getPrototypeOf(new view.Blob()); -}(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content || this)); -} - /* eslint-enable */ diff --git a/app/scripts/vendor/FileSaver.js b/app/scripts/vendor/FileSaver.js deleted file mode 100644 index 910a217e1e..0000000000 --- a/app/scripts/vendor/FileSaver.js +++ /dev/null @@ -1,260 +0,0 @@ -/* eslint-disable */ -/* FileSaver.js - * A saveAs() FileSaver implementation. - * 2015-05-07.2 - * - * By Eli Grey, http://eligrey.com - * License: X11/MIT - * See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md - */ - -/*global self */ -/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */ - -/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ - -if(typeof window !== "undefined") { - -var saveAs = saveAs || (function(view) { - "use strict"; - // IE <10 is explicitly unsupported - if (typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) { - return; - } - var - doc = view.document - // only get URL when necessary in case Blob.js hasn't overridden it yet - , get_URL = function() { - return view.URL || view.webkitURL || view; - } - , save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a") - , can_use_save_link = "download" in save_link - , click = function(node) { - var event = doc.createEvent("MouseEvents"); - event.initMouseEvent( - "click", true, false, view, 0, 0, 0, 0, 0 - , false, false, false, false, 0, null - ); - node.dispatchEvent(event); - } - , webkit_req_fs = view.webkitRequestFileSystem - , req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem - , throw_outside = function(ex) { - (view.setImmediate || view.setTimeout)(function() { - throw ex; - }, 0); - } - , force_saveable_type = "application/octet-stream" - , fs_min_size = 0 - // See https://code.google.com/p/chromium/issues/detail?id=375297#c7 and - // https://github.com/eligrey/FileSaver.js/commit/485930a#commitcomment-8768047 - // for the reasoning behind the timeout and revocation flow - , arbitrary_revoke_timeout = 500 // in ms - , revoke = function(file) { - var revoker = function() { - if (typeof file === "string") { // file is an object URL - get_URL().revokeObjectURL(file); - } else { // file is a File - file.remove(); - } - }; - if (view.chrome) { - revoker(); - } else { - setTimeout(revoker, arbitrary_revoke_timeout); - } - } - , dispatch = function(filesaver, event_types, event) { - event_types = [].concat(event_types); - var i = event_types.length; - while (i--) { - var listener = filesaver["on" + event_types[i]]; - if (typeof listener === "function") { - try { - listener.call(filesaver, event || filesaver); - } catch (ex) { - throw_outside(ex); - } - } - } - } - , auto_bom = function(blob) { - // prepend BOM for UTF-8 XML and text/* types (including HTML) - if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) { - return new Blob(["\ufeff", blob], {type: blob.type}); - } - return blob; - } - , FileSaver = function(blob, name) { - blob = auto_bom(blob); - // First try a.download, then web filesystem, then object URLs - var - filesaver = this - , type = blob.type - , blob_changed = false - , object_url - , target_view - , dispatch_all = function() { - dispatch(filesaver, "writestart progress write writeend".split(" ")); - } - // on any filesys errors revert to saving with object URLs - , fs_error = function() { - // don't create more object URLs than needed - if (blob_changed || !object_url) { - object_url = get_URL().createObjectURL(blob); - } - if (target_view) { - target_view.location.href = object_url; - } else { - var new_tab = view.open(object_url, "_blank"); - if (new_tab == undefined && typeof safari !== "undefined") { - //Apple do not allow window.open, see http://bit.ly/1kZffRI - view.location.href = object_url - } - } - filesaver.readyState = filesaver.DONE; - dispatch_all(); - revoke(object_url); - } - , abortable = function(func) { - return function() { - if (filesaver.readyState !== filesaver.DONE) { - return func.apply(this, arguments); - } - }; - } - , create_if_not_found = {create: true, exclusive: false} - , slice - ; - filesaver.readyState = filesaver.INIT; - if (!name) { - name = "download"; - } - if (can_use_save_link) { - object_url = get_URL().createObjectURL(blob); - save_link.href = object_url; - save_link.download = name; - click(save_link); - filesaver.readyState = filesaver.DONE; - dispatch_all(); - revoke(object_url); - return; - } - // Object and web filesystem URLs have a problem saving in Google Chrome when - // viewed in a tab, so I force save with application/octet-stream - // http://code.google.com/p/chromium/issues/detail?id=91158 - // Update: Google errantly closed 91158, I submitted it again: - // https://code.google.com/p/chromium/issues/detail?id=389642 - if (view.chrome && type && type !== force_saveable_type) { - slice = blob.slice || blob.webkitSlice; - blob = slice.call(blob, 0, blob.size, force_saveable_type); - blob_changed = true; - } - // Since I can't be sure that the guessed media type will trigger a download - // in WebKit, I append .download to the filename. - // https://bugs.webkit.org/show_bug.cgi?id=65440 - if (webkit_req_fs && name !== "download") { - name += ".download"; - } - if (type === force_saveable_type || webkit_req_fs) { - target_view = view; - } - if (!req_fs) { - fs_error(); - return; - } - fs_min_size += blob.size; - req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) { - fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) { - var save = function() { - dir.getFile(name, create_if_not_found, abortable(function(file) { - file.createWriter(abortable(function(writer) { - writer.onwriteend = function(event) { - target_view.location.href = file.toURL(); - filesaver.readyState = filesaver.DONE; - dispatch(filesaver, "writeend", event); - revoke(file); - }; - writer.onerror = function() { - var error = writer.error; - if (error.code !== error.ABORT_ERR) { - fs_error(); - } - }; - "writestart progress write abort".split(" ").forEach(function(event) { - writer["on" + event] = filesaver["on" + event]; - }); - writer.write(blob); - filesaver.abort = function() { - writer.abort(); - filesaver.readyState = filesaver.DONE; - }; - filesaver.readyState = filesaver.WRITING; - }), fs_error); - }), fs_error); - }; - dir.getFile(name, {create: false}, abortable(function(file) { - // delete file if it already exists - file.remove(); - save(); - }), abortable(function(ex) { - if (ex.code === ex.NOT_FOUND_ERR) { - save(); - } else { - fs_error(); - } - })); - }), fs_error); - }), fs_error); - } - , FS_proto = FileSaver.prototype - , saveAs = function(blob, name) { - return new FileSaver(blob, name); - } - ; - // IE 10+ (native saveAs) - if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) { - return function(blob, name) { - return navigator.msSaveOrOpenBlob(auto_bom(blob), name); - }; - } - - FS_proto.abort = function() { - var filesaver = this; - filesaver.readyState = filesaver.DONE; - dispatch(filesaver, "abort"); - }; - FS_proto.readyState = FS_proto.INIT = 0; - FS_proto.WRITING = 1; - FS_proto.DONE = 2; - - FS_proto.error = - FS_proto.onwritestart = - FS_proto.onprogress = - FS_proto.onwrite = - FS_proto.onabort = - FS_proto.onerror = - FS_proto.onwriteend = - null; - - return saveAs; -}( - typeof self !== "undefined" && self - || typeof window !== "undefined" && window - || this && this.content -)); -// `self` is undefined in Firefox for Android content script context -// while `this` is nsIContentFrameMessageManager -// with an attribute `content` that corresponds to the window - -if (typeof module !== "undefined" && module.exports) { - module.exports.saveAs = saveAs; -} else if ((typeof define !== "undefined" && define !== null) && (define.amd != null)) { - define([], function() { - return saveAs; - }); -} -} else { - // nope -} -/* eslint-enable */ diff --git a/app/styles/common/_repository-list-item.scss b/app/styles/common/_repository-list-item.scss deleted file mode 100644 index 1cd1411c48..0000000000 --- a/app/styles/common/_repository-list-item.scss +++ /dev/null @@ -1,98 +0,0 @@ -.repository-list-item { - display: flex; - flex-flow: row; - border: 1px solid $secondary-5; - border-radius: $global-radius; - margin: 1rem; - font-weight: $font-weight-bold; - color: $secondary-2; - background: $white; - &:hover { - border-color: $primary-1; - .section { - &.action { - background-color: $primary-1; - color: white; - border-color: $primary-1; - } - } - } - > a { - display: flex; - flex: 1; - } - .avatar { - background: $primary-color; - width: 50px; - height: 50px; - border-radius: $global-radius; - } - .section { - display: flex; - border-left: 1px solid $secondary-5; - padding: 1rem; - flex-flow: row; - &.head { - flex-grow: 1; - } - &:first-child { - border-left: 0; - } - &.stats { - min-width: 100px; - text-align: center; - } - &.action { - background-color: $secondary-5;; - color: $secondary-4; - flex-flow: column; - i { - position: relative; - top: 0.5rem; - left: 1.2rem; - } - .text { - margin-top: 1.2rem; - margin-left: 0.4rem; - font-size: 0.7rem; - } - } - .title { - padding-left: 1rem; - padding-right: 1rem; - padding-top: 0.25rem; - } - .labels { - font-size: rem-calc(12px); - color: $secondary-4; - .official { - color: $primary-1; - } - .public { - color: darken($primary-1, 30%); - } - .private { - color: darken($primary-6, 35%); - } - .automated { - color: $secondary-4; - } - } - .label-value { - padding-top: 0.25rem; - margin: 0 auto; - .value { - font-size: rem-calc(14px); - margin-bottom: 0.25rem; - color: $secondary-3; - } - .sub-label { - font-size: rem-calc(10px); - color: $secondary-3; - } - } - .repo-name { - font-size: rem-calc(18px); - } - } -} diff --git a/app/styles/font-awesome.min.css b/app/styles/font-awesome.min.css deleted file mode 100644 index 9c24364d62..0000000000 --- a/app/styles/font-awesome.min.css +++ /dev/null @@ -1,4 +0,0 @@ -/*! - * Font Awesome 4.4.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.4.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.4.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.4.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.4.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.4.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.4.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"} \ No newline at end of file diff --git a/app/styles/hub.scss b/app/styles/hub.scss deleted file mode 100644 index 3ec7183cf9..0000000000 --- a/app/styles/hub.scss +++ /dev/null @@ -1,18 +0,0 @@ -@import 'hub/account'; -@import 'hub/autobuilds'; -@import 'hub/badge'; -@import 'hub/blankslate'; -@import 'hub/flyout-menu'; -@import 'hub/react-tagsinput'; -@import 'hub/main-nav'; -@import 'hub/profile'; -@import 'hub/repositories'; -@import 'hub/repository-settings'; -@import 'hub/reset-password'; -@import 'hub/search'; -@import 'hub/tabs'; -@import 'hub/type'; -@import 'hub/usericons'; -@import 'hub/welcome'; -@import 'hub/forms'; -@import 'hub/docker-trusted-registry'; diff --git a/app/styles/hub/_blankslate.scss b/app/styles/hub/_blankslate.scss deleted file mode 100644 index 7fb8a37d73..0000000000 --- a/app/styles/hub/_blankslate.scss +++ /dev/null @@ -1,84 +0,0 @@ -/* - * For pages without content - * - */ - -.blankslate { - text-align: center; - background: #fff; - border-bottom: 1px solid #cbd1d7; - padding: 2.4rem; - h1 { - font-size: 2.5em; - } - .fa { - color: #566471; - font-size: 4em; - margin-bottom: 15px; - } -} - -.blankslate-alt { - text-align: center; - padding: 5rem; -} - -/* - * - * buttons : TODO: MOVE TO FOUNDATION OVERRIDES & SPLIT OUT THESE RANDOM BUTTONS - * - */ - -button, -.button, -.profile-settings .change-pass-form .change-pass-save .button, -.settings-wrapper input[type='submit'] { - -moz-appearance: none; - border-radius: $global-radius; - border-color: #1298c6; - border-style: solid; - border-width: 0; - color: #ffffff; - cursor: pointer; - display: inline-block; - font-size: 1rem; - font-weight: normal; - margin: 0 0 1.25rem; - padding: 0.7rem 1rem 0.7rem 0.9rem; - text-align: center; - transition: background-color 300ms ease-out 0s; - box-shadow: none; - &.default { - background-color: #fff; - border: 1px solid #dfe4ea; - color: #000; - } - &.primary { - background: $primary-1; - border-radius: $global-radius; - color: #fff; - &:hover { - background: $primary-2; - } - } - // &.secondary {/** will switch this with .default **/} - &.dashed { - background-color: transparent; - border: 1px dashed #c3ccd9; - color: #2f4559;/** need variable **/ - border-radius: $global-radius; - &:hover { - opacity: .8; - } - } - &.button.disabled { - cursor: not-allowed; - } - &.small { - padding: 0.7rem 1rem 0.7rem 0.9rem; - } - &.xl { - padding: 1rem 2rem 1rem 2rem; - margin-right: 1rem; - } -} diff --git a/app/styles/hub/_profile.scss b/app/styles/hub/_profile.scss deleted file mode 100644 index cca73f4675..0000000000 --- a/app/styles/hub/_profile.scss +++ /dev/null @@ -1,30 +0,0 @@ -.gravatar { - margin: 1.5rem 0; - img { - border: 1px solid $secondary-5; - border-radius: $global-radius; - } -} - -.profile-info { - padding: .5rem 1rem 0 1rem; - ul { - padding: .6rem 0; - li { - padding: .2rem 0; - color: $secondary-4; - .fa { - margin: 0 .5rem 0 0; - min-width: .8rem; - text-align: center; - } - } - } -} - -.profile-repos { - padding: 1rem 0; - h4 { - padding-left: 2rem; - } -} diff --git a/app/styles/hub/_type.scss b/app/styles/hub/_type.scss deleted file mode 100644 index 683ab8a3cd..0000000000 --- a/app/styles/hub/_type.scss +++ /dev/null @@ -1,19 +0,0 @@ -/* - * This file is in progress - will contain global typography styles - * - */ -h1, -h2, -h3, -h4, -h5, -h6 { - color: $primary-1; - font-weight: 200; -} -h1 { - font-size: 1.8875rem; -} -h2 { - font-size: 1.3875rem; -} \ No newline at end of file diff --git a/app/styles/hub/account.scss b/app/styles/hub/account.scss deleted file mode 100644 index 5d577764e4..0000000000 --- a/app/styles/hub/account.scss +++ /dev/null @@ -1,518 +0,0 @@ -.settings-wrapper { - width: 100%; - input { - &[type='text'],&[type='email'],&[type='password'] { - color: $secondary-1; - } - &[type='submit'] { - padding: .5rem; - } - } - .settings-body { - padding: 25px 0px; - .account-section-text { - float: left; - display:inline-block; - } - .account-section-header { - padding-left: 0; - .account-section-title{ - color: $secondary-1; - font-weight: $font-weight-bold; - } - .account-section-subtitle{ - color: $primary-2; - margin-bottom: .5rem; - } - } - .account-section { - margin-bottom: 2rem; - .columns:last-child { - float: left; - } - } - } -} - -.profile-settings { - .default-repo-visibility { - padding: 1rem; - .visibility-toggle { - &:hover { - cursor: pointer; - cursor: hand; - } - input { - margin-right: .5rem; - } - } - } - .email-wrapper { - border: 1px solid $border-input; - background: white; - form { - .add-email { - padding: 2rem 1rem 0; - .email-title { - font-weight: $font-weight-bold; - } - } - .email-element { - height: 4rem; - padding: 0 1rem; - margin: .5rem .5rem; - display: flex; - align-items: left; - .emphasis {/** TODO: Scope to .email-element for the moment, however will mostly be global **/ - color: $secondary-3; - font-weight: 800; - } - .fa-times {/** TODO: Scope to .email-element for the moment, however will mostly be global **/ - color: $primary-5; - font-size: 1.3rem; - &:hover { - color: $secondary-1; - } - } - .close-button {/** TODO: Let's verify we still need this **/ - color: white; - display: inline-block; - background: $docker-dark--placeholders; - border-radius: 100%; - width: 1.5rem; - height: 1.5rem; - text-align: center; - margin-right: .5rem; - float: right; - &:hover { - background: darken($docker-dark--placeholders, 10%); - } - } - .email-action { - text-align: center; - border-radius: 1rem; - &.status-sent { - border: 1px solid $primary-2; - color: $primary-2; - } - &.status-sending { - border: 1px solid $primary-1; - color: $primary-1; - } - &.status-failed { - border: 1px solid $primary-5; - color: $primary-5; - } - } - .email-address { - word-wrap: break-word; - } - } - } - } - .change-pass-form { - border: 1px solid $border-input; - background: white; - padding: 3rem 3rem 1rem 3rem; - .change-pass-save { - height: 250px; - display: flex; - align-items: flex-end; - .button { - padding:.5rem; - } - } - &.success { - border: 1px solid $primary-2; - } - &.form-error { - border: 1px solid $primary-5; - } - } - .account-info-wrapper { - border: 1px solid $border-input; - background: white; - padding: 3rem 3rem 1rem; - .button { - float: right; - } - &.success { - border: 1px solid $primary-2; - } - &.form-error { - border: 1px solid $primary-5; - } - } - .toOrgButton { - padding: .5rem 0; - } -} -.convert-to-org{ - .toOrg-title { - font-weight: $font-weight-bold; - } - .toOrg-body { - margin-bottom: 1rem; - } - .warning { - text-align: center; - color: $primary-5; - } - .convert-org-form { - padding: 3rem 2rem .5rem; - background: white; - border: 1px solid $border-input; - .button { - padding:.5rem; - &:disabled { - background: $secondary-5; - } - } - } -} - -.accounts-services { - .linked-accounts { - margin-bottom: 5rem; - .link-service { - padding: 1.25rem; - margin: 0 1rem; - height: 13rem; - border: 1px solid $border-input; - background: white; - float: left; - .service-title { - display:flex; - align-items: center; - .linked-icon { - width: 100%; - height: auto; - } - .service-name { - font-weight: $font-weight-bold; - margin: 0 1rem; - } - } - .user-access { - margin: .5rem 0 0; - } - .button { - margin: 1rem 0 0; - float: right; - } - } - } -} - -.account-notifications { - form { - background: white; - border: 1px solid $border-input; - padding: 2rem 2rem 1rem; - .button { - margin-right: 1rem; - // padding: .5rem; - float: right; - } - &.success { - border: 1px solid $primary-2; - } - &.form-error { - border: 1px solid $primary-5; - } - } - .event-notifs { - margin-bottom: 5rem; - } - .notification { - margin-bottom: 1rem; - &:hover { - cursor: pointer; - cursor: hand; - } - &.unverified { - color: $secondary-4; - cursor: default; - } - } -} - -.billing-plans { - .columns:last-child { - float: left; - } - .account-billing-info { - margin-left: .5rem; - } - .plans-error-message { - background: $alert-color; - color:white; - } - .plans-q { - .q-title { - font-weight: 500; - color: $primary-2; - } - .q-answer { - padding-left: 1rem; - } - margin-bottom: 2rem; - } - .billing-info { - background: white; - border: 1px solid $border-input; - padding: 2rem 0rem 2rem 2rem; - margin: .5rem; - .row { - margin-bottom: 1rem; - .info-content { - border-left: 1px solid $border-input; - padding: .5rem 3rem; - } - .no-account { - text-align: center; - } - } - } - .billing-form-wrapper { - border: 1px solid $border-input; - background: white; - padding: 3rem 3rem 1rem; - .billing-form-header { - text-align: center; - } - .billing-info-form { - .billing-form-section { - margin-bottom: 1.5rem; - } - .billing-field * { - width: 100%; - } - .billing-dropdown { - width: 100%; - &.error { - border: 1px solid $alert-color; - } - } - .accepted-cards { - margin-bottom: 35px; - .card-icon { - font-size: 1.5rem; - margin-left: .5rem; - } - } - .above-selects .group { - margin-bottom: 15px; - } - .selects { - .date-text { - text-align: center; - height: 2rem; - display: flex; - align-items: center; - } - .columns { - margin-bottom: 20px; - } - } - .back { - margin-left: 2rem; - } - } - } - .preview-box { - border: 1px solid $border-input; - background: white; - padding: 2rem 2rem 0; - margin-left: 1rem; - .total { - margin-bottom: 35px; - } - .coupon_code * { - width: 100%; - } - .price { - text-align: right; - } - } - .invoice-table { - a.not-active { - pointer-events: none; - cursor: default; - color: $secondary-5; - } - } -} -.orgs-body { - padding-top: rem-calc(15px); - padding-bottom: rem-calc(20px); -} - -.orgs-grid { - margin-left: 1.6rem; -} - -.orgs-settings { - h5 { - font-weight: 400; - color: #22b8eb;/** find varible and update */ - float: left; - margin: 0 0 0.8rem 1rem; - // color: $docker-dark; - } - .page-header-buttons { - float: left; - padding-left: 20px; - button { - margin-right: rem-calc(10px); - } - } - .new-org-form { - width: 100%; - } - .org-details { - ul { - list-style: none; - margin-left: 0; - li { - background-color: $panel-bg; - padding: rem-calc(10px); - margin-bottom: rem-calc(5px); - border-radius: rem-calc(2px); - margin: 0 .2rem 0 0; - } - } - .org-team-md { - margin-left: rem-calc(-15px); - .inline-list { - margin: 0; - } - h5 { - margin-left: rem-calc(10px); - font-weight: 300; - font-color: #22b8eb; - } - h6 { - background-color: lighten($panel-bg, 8%); - border-radius: $global-radius; - padding: 10px; - .action-icon { - background-color: lighten($panel-bg, 8%); - } - } - .org-members { - li { - img { - margin-right: rem-calc(10px); - border-radius: 100%; - } - width: rem-calc(200px); - padding: rem-calc(12px); - margin-right: rem-calc(20px); - } - } - // .org-teams {} - } - /** hide border when dux-form is in tabs **/ - .dux-form { - border: 0; - } - } - .tab-title { - border: 1px solid #c4cdda; - border-bottom: none; - border-top-left-radius: $global-radius; - border-top-right-radius: $global-radius; - background-color: #e6edf4; - padding: 0.5rem; - &:hover { - cursor: pointer; - color: #23b8eb; - } - } - .tab-title.active { - background-color: white; - } - .tabs-content { - border-bottom-left-radius: $global-radius; - border-bottom-right-radius: $global-radius; - border-top-right-radius: $global-radius; - border: 1px solid #c4cdda; - background-color: white; - padding: rem-calc(20px); - } -} - -//Teams -.team-item { - a { - margin-left: rem-calc(15px); - } -} - -.add-team-container { - form { - margin-top: 1.6rem; - .alert-box { - margin-left: 0.5rem !important; - margin-right: 0.5rem !important; - } - } -} - -.add-team-button-group { - input[type="submit"], input[type="reset"] { - border-radius: $global-radius; - margin-left: 1rem; - } -} - -//global -li.li-no-hover { - &:hover { - background-color: transparent !important; - } -} - -.delete-member-item { - height: rem-calc(25px); - cursor: default; - a { - float: left; - margin-left: 0.7rem; - } - i { - margin-top: 0.3rem; - margin-right: 1.4rem; - cursor: pointer; - color: #FF5151; - } -} -.add-member-item { - height: rem-calc(25px); - cursor: text; - input[type="text"] { - font-size: rem-calc(16px); - margin-left: 0.5rem; - float: left; - border: 0; - height: 2rem; - line-height: 2rem; - color: $gray-2; - width: rem-calc(500px); - &:hover { - color: $gray-2; - } - &:active { - color: $gray-2; - } - &:focus { - color: $gray-2; - } - } - i { - margin-top: 0.3rem; - margin-right: -1.5rem; - cursor: pointer; - } -} diff --git a/app/styles/hub/autobuilds.scss b/app/styles/hub/autobuilds.scss deleted file mode 100644 index f95ba83e46..0000000000 --- a/app/styles/hub/autobuilds.scss +++ /dev/null @@ -1,108 +0,0 @@ -.ol-decimal { - list-style-type: decimal; -} - -.auto-build-tags-table { - input[type="text"] { - max-width:180px; - } -} - -.autobuild-checkbox { - font-size: 14px; - font-weight: 300; - cursor: pointer; - * { - cursor: pointer; - } - .checkbox-text { - margin-left: 5px; - } -} - -//GLOBAL? -.two-level-selector { - margin-top: 1.0rem; - .dux-form { - padding: 0; - margin: 0; - } - .row { - padding: 0; - margin: 0; - .columns { - padding: 0; - } - } - //this is actually a lighter filter bar - .searchbar input[type=text] { - background-color: $secondary-4; - width: 100%; - } - .filterbar-container { - margin-left: rem-calc(24px); - } -} - -//Strip out the module class -ul.stripped-module { - background: #fff; - list-style: none; - padding: 0 !important; - margin: 0 !important; - li { - text-align: left; - border-bottom: 1px solid #cbd1d7; - padding-top: 0.5rem; - padding-bottom: 0.5rem; - &:hover { - background: $secondary-6; - cursor: pointer; - } - .list-item { - padding-left: 1rem; - padding-right: 1rem; - } - } - img { - border-radius: $global-radius; - } - .header-bar { - background-color: $secondary-6; - min-height: rem-calc(60px); - cursor: default; - } - .header-title { - margin-left: 1rem; - margin-top: 0.5rem; - font-size: rem-calc(18px); - font-weight: 400; - } - .alert-box { - margin-left: 0.5rem; - margin-right: 0.5rem; - } -} - -ul.left-border { - border-left: 1px solid #cbd1d7; -} - -ul.right-border { - border-right: 1px solid #cbd1d7; -} - -//fa i class needs this -.arrow-sel { - margin-top: 0.25rem; - margin-right: 0.25rem; -} - -.create-autobuild-form { - .form-error { - border: 1px solid $primary-5; - } - .text-error { - color: $primary-5; - } -} diff --git a/app/styles/hub/badge.scss b/app/styles/hub/badge.scss deleted file mode 100644 index f17d6adac9..0000000000 --- a/app/styles/hub/badge.scss +++ /dev/null @@ -1,11 +0,0 @@ -.dux-badge { - border-radius: rem-calc(4px); - padding: rem-calc(3px); - &.official { - color: #23b8eb; - } - &.builds { - color: #86d800; - font-size: rem-calc(12px); - } -} diff --git a/app/styles/hub/flyout-menu.scss b/app/styles/hub/flyout-menu.scss deleted file mode 100644 index e8234f592f..0000000000 --- a/app/styles/hub/flyout-menu.scss +++ /dev/null @@ -1,185 +0,0 @@ -//@extend-elements -//original selectors -//.cssmenu ul, .cssmenu ul li, .cssmenu ul ul -%extend_1 { - list-style: none; - margin: 0; - padding: 0; -} - -//original selectors -//.cssmenu ul li.hover, .cssmenu ul li:hover -%extend_2 { - position: relative; - z-index: 599; - cursor: default; -} - - -@charset "UTF-8"; -.cssmenu { - padding: 0; - margin: 0; - border: 0; - line-height: 1; - width: 100%; - background: $panel-bg; - font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; - zoom: 1; - font-size: 12px; - ul { - @extend %extend_1; - position: relative; - z-index: 597; - float: left; - li { - @extend %extend_1; - min-height: 1px; - line-height: 3rem; - vertical-align: middle; - position: relative; - float: none; - &.hover { - @extend %extend_2; - } - &:hover { - @extend %extend_2; - > ul { - visibility: visible; - } - } - &.has-sub > a:after { - content: '+'; - position: absolute; - top: 50%; - right: 15px; - margin-top: -6px; - } - } - ul { - @extend %extend_1; - visibility: hidden; - position: absolute; - z-index: 598; - top: 0; - left: 100%; - margin-top: 0; - width: 100%; - //Instead of the line below you could use @includeborder-radius($radius, $vertical-radius) - border: 1px solid $panel-bg; - li { - float: none; - font-weight: normal; - border-bottom: 1px solid $panel-bg; - &.first { - //Instead of the line below you could use @includeborder-radius($radius, $vertical-radius) - border-radius: 0 3px 0 0; - } - &.last { - //Instead of the line below you could use @includeborder-radius($radius, $vertical-radius) - border-radius: 0 0 3px 0; - border-bottom: 0; - } - &:hover > a { - background: $button-bg-color; - color: $ghost; - } - } - ul { - top: -2px; - right: 0; - } - a { - font-size: 14px; - color: $ghost; - &:hover { - color: $ghost; - } - } - } - } - &:before { - content: ''; - display: block; - } - &:after { - content: ''; - display: table; - clear: both; - } - a { - display: block; - padding: 15px 20px; - color: $ghost; - text-decoration: none; - text-transform: uppercase; - } - li { - position: relative; - } - &.align-right { - float: right; - li { - text-align: right; - } - ul { - ul { - visibility: hidden; - position: absolute; - top: 0; - left: -100%; - z-index: 598; - width: 100%; - //Instead of the line below you could use @includeborder-radius($radius, $vertical-radius) - border-radius: $global-radius 0 0 $global-radius; - li { - &.first { - //Instead of the line below you could use @includeborder-radius($radius, $vertical-radius) - border-radius: $global-radius 0 0 0; - } - &.last { - //Instead of the line below you could use @includeborder-radius($radius, $vertical-radius) - border-radius: 0 0 0 $global-radius; - } - } - } - li.has-sub > a { - &:before { - content: '+'; - position: absolute; - top: 50%; - left: 15px; - margin-top: -6px; - } - &:after { - content: none; - } - } - } - > ul > li > a { - border-left: 2px solid lighten($panel-bg, 10%); - border-right: none; - } - } - > ul { - width: 100%; - > li { - > a { - border-right: 2px solid lighten($panel-bg, 10%); - color: $ghost; - &:hover { - color: $ghost; - } - } - &.active a { - background: lighten($panel-bg, 10%); - } - a:hover { - background: lighten($panel-bg, 10%); - } - &:hover a { - background: lighten($panel-bg, 10%); - } - } - } -} diff --git a/app/styles/hub/main-nav.scss b/app/styles/hub/main-nav.scss deleted file mode 100644 index 4683e7b2c0..0000000000 --- a/app/styles/hub/main-nav.scss +++ /dev/null @@ -1,132 +0,0 @@ -/* - * These top bar properties still need to be sassified. - * - */ - -.topnav-wrapper { - background-color: $topbar-dark; -} - -.top-bar .top-bar-section ul li:hover:not(.has-form) > a { - background: transparent; -} - -.top-bar-section ul li > a { - font-weight: 400; - font-size: 14px; -} - -.top-bar-section ul li > a.button.secondary:hover, -.top-bar-section ul li > a.button.secondary:focus { - color: #fff; - background: transparent; -} - -.top-bar-section ul li > a.button.secondary { - background-color: transparent; - color: #c4cdda; - font-size: 1em; - height: 40px; - margin-top: -3px; -} -.top-bar-section li:not(.has-form) a:not(.button) { - background: transparent; - line-height: 3.125rem; -} -/* - * - * - */ - -.top-bar-section { - ul li { - background: none; - a.button.tiny { - background-color: #86d800;/** temp color **/ - border-radius: $global-radius; - box-shadow: none; - &:hover { - background-color: #5fa736;/** temp color **/ - } - } - } - .profile-photo { - width: rem-calc(24px); - height: rem-calc(24px); - margin-right: 5px; - border-radius: $global-radius; - } - .title-area { - margin-top: .5rem; - a { - padding: 1rem; - } - img { - height: 36px; - margin-right: 10px - } - } - .nav-user-info { - background: none; - } - /* - * "+" menu - * - */ - .css-dropdown { - &:hover ul { - display: block; - opacity: 1; - visibility: visible; - } - ul:before { - border: 8px solid transparent; - border-bottom-color: #3d4c5a; - content: ""; - display: inline-block; - left: 90px; - position: absolute; - top: -16px; - } - ul { - // background: $topbar-dark; - background: #3d4c5a; - border-bottom-left-radius: 5px; - border-bottom-right-radius: 5px; - display: none; - padding: 0; - position: absolute; - top: 48px; - right: 4rem; - opacity: 0; - padding: .5rem 0; - visibility: hidden; - width: 220px; - z-index: 1; - li { - cursor: pointer; - float: none; - padding: .3em; - margin: 0; - position: relative; - a { - display: block; - padding-top: .23rem; - } - a:hover { - background: #7a8491; - } - } - li:not(.has-form) > a { - line-height: 1.7rem; - } - & i.fa { - font-size: 1.2rem; - padding-right: 7px; - } - &.with-button { - right: rem-calc(116px); - } - } - } -} \ No newline at end of file diff --git a/app/styles/hub/react-tagsinput.scss b/app/styles/hub/react-tagsinput.scss deleted file mode 100644 index 70287eee8f..0000000000 --- a/app/styles/hub/react-tagsinput.scss +++ /dev/null @@ -1,59 +0,0 @@ -//colors -$color_celeste_approx: #ccc; -$white: #fff; -$color_conifer_approx: #a5d24a; -$color_deco_approx: #cde69c; -$color_olive_drab_approx: #638421; -$color_cosmos_approx: #fbd8db; -$color_tamarillo_approx: #90111a; -$color_tapa_approx: #777; - -.react-tagsinput { - border: 1px solid lighten($panel-bg, 5%); - background: lighten($panel-bg, 8%); - padding: rem-calc(10px); - overflow-y: auto; - //Instead of the line below you could use @includeborder-radius($radius, $vertical-radius) - border-radius: rem-calc(2px); - input { - color: $charcoal; - } -} -.react-tagsinput-tag { - display: block; - border: 1px solid $secondary-5; - background: $secondary-6; - color: $oil; - font-size: 14px; - float: left; - padding: 15px; - margin-right: 10px; - margin-bottom: 10px; - text-decoration: none; - //Instead of the line below you could use @includeborder-radius($radius, $vertical-radius) - border-radius: $global-radius; -} -.react-tagsinput-invalid { - background: transparent; - color: $primary-5; -} -.react-tagsinput-remove { - font-weight: 300; - color: $secondary-4; - text-decoration: none; - font-size: 14px; - cursor: pointer; - &:before { - content: "x"; - } -} -.react-tagsinput-input { - background: transparent; - color: $charcoal; - border: 0; - font-size: 13px; - padding: 5px; - margin: 0; - width: 80px; - outline: none; -} \ No newline at end of file diff --git a/app/styles/hub/repositories.scss b/app/styles/hub/repositories.scss deleted file mode 100644 index 3323d95ff8..0000000000 --- a/app/styles/hub/repositories.scss +++ /dev/null @@ -1,155 +0,0 @@ -ul.repositories { - margin: 2.25rem 0.3rem 0 0.3rem; -} -.repo-header { - padding: rem-calc(10px); -} -.repo-content { - padding: rem-calc(10px); -} -.repository { - background: white; - .title { - color: $primary-color; - } - .logo { - width: 64px; - min-width: 64px; - height: 64px; - min-height: 64px; - padding: 10px; - background: $primary-color; - border-radius: $global-radius; - .d-logo { - color: $ghost; - font-size: rem-calc(48px); - margin: 0 auto; - } - } - .header { - padding-top: 0.325rem; - h6 small { - font-size: small; - } - h6 span { - font-size: small; - text-transform: capitalize; - color: #3f5167; - } - } - .repo-wrapper { - margin-left: 0.5rem; - margin-right: 0.5rem; - } - //TODO: These surely should be `scss-ified` - .repo-stars { - border: 1px solid #c4cdda; - border-left: none; - padding: 10px; - p { - font-size: smaller; - } - } - .repo-downloads { - border: 1px solid #c4cdda; - border-left: none; - border-right: none; - padding: 10px; - p { - font-size: smaller; - } - } -} - -.repo-separator { - font-weight: 300; - font-size: rem-calc(24px); - margin-right: 0px; - padding-right: 0px; - width: 20px; -} - -.repo-form-margin { - margin-left: -15px; -} - -//Need this to make foundation block-grid work with our design and borders -.repo-border { - border:1px solid white; - position:relative; - z-index:10 -} - -.repo-border:before { - content:""; - display:block; - position:absolute; - top:2px; - left:2px; - right:2px; - bottom:2px; - border:1px solid #c4cdda; - border-radius: $global-radius; -} - -.repository-page { - .repo-description-dockerfile { - .dockerfile { - font-family: $font-family-monospace; - white-space: pre; - overflow-x: auto; - } - } - .repo-details-content { - .repo-visibility { - margin-bottom: 1.25rem; - background: white; - border: 1px solid $docker-dark--placeholders; - padding: .75rem 1rem; - .privacy { - font-weight: $font-weight-bold; - display: inline-block; - } - .status { - display: inline-block; - } - } - - - - .temp-prof-icon { - height: 50px; - width: 50px; - border-radius: 100%; - border: 1px solid black; - display: inline-block; - margin-right: 10px; - } - } -} - -.explore-repo-list { - margin-top: 1rem; -} - -.add-repository-form { - margin-top: rem-calc(20px); -} - -.repo-tags { - margin: 0; - padding: 0; - list-style-type: none; - li { - float: left; - padding: 0.3rem 0.3rem 1rem 0; - margin-right: 0.5rem; - .repo-tag { - background-color: #3c5164; - color: white; - border-radius: $global-radius; - padding: 0.5rem 0.8rem; - } - } -} - diff --git a/app/styles/hub/repository-settings.scss b/app/styles/hub/repository-settings.scss deleted file mode 100644 index bf957d5600..0000000000 --- a/app/styles/hub/repository-settings.scss +++ /dev/null @@ -1,49 +0,0 @@ -.repo-settings { - color: $charcoal; - padding: 1rem; - h1, h2, h3, h4, h5, h6, input, label { - color: $charcoal; - } - .form-panel { - @include panel(); - background: $white; - button { - margin-right: $default-margin; - } - } - .help-text { - padding: 1rem 0 0 .9rem; - } - /** scope this to repo-settings only **/ - input[type="text"], - .bar { - width: 100%; - } - .repo-visibility { - margin-top: 1rem; - .visibility-form { - .visibility-toggle { - cursor: pointer; - * { - cursor: pointer; - } - .text-error { - color: $primary-5; - margin-left: 1rem; - } - } - .disabled { - cursor: default; - color: $secondary-5; - * { - cursor: default; - } - } - input { - &[name='visibility'] { - margin-right: 5px; - } - } - } - } -} diff --git a/app/styles/hub/reset-password.scss b/app/styles/hub/reset-password.scss deleted file mode 100644 index 810a6bf95d..0000000000 --- a/app/styles/hub/reset-password.scss +++ /dev/null @@ -1,49 +0,0 @@ -.pass-reset-wrapper { - align-items: center; - display: flex; - height: 100%; - width: 100%; - &.reset { - text-align: center; - } - .password-reset { - background-color: $white; - border: 1px solid rgb(233, 237, 240);// TODO: create/utilize variable - border-radius: $global-radius; - display: flex; - flex-direction: column; - justify-content: center; - min-height: 270px; - h3 { - color: $primary-1; - font-weight: 300; - } - &.error h3 { - color: $primary-5; - } - p { - color: rgb(113, 125, 144);// TODO: create/utilize variable - } - form { - margin-top: .6rem; - } - .group { - input, - .bar { - color: rgb(113, 125, 144);// TODO: create/utilize variable - width: 100%; - } - } - .resetPassSubmit { - background-color:$primary-color; - border: none; - border-radius: $global-radius; - color: $white; - float: right; - padding: 10px 20px; - &:disabled { - background-color:rgb(233, 237, 240);// TODO: create/utilize variable - } - } - } -} diff --git a/app/styles/hub/search.scss b/app/styles/hub/search.scss deleted file mode 100644 index a0a665c2e2..0000000000 --- a/app/styles/hub/search.scss +++ /dev/null @@ -1,191 +0,0 @@ -//search page -.search-page { - width: 100%; - overflow-x: hidden; - font-weight: 300; - .inline-list { - margin-top: rem-calc(12px); - li { - margin-left: 0.7rem; - } - } - select { - background-color: transparent; - border: 1px solid #c4cdda; - transition: border-color 0.15s linear 0s, background 0.15s linear 0s; - outline: 0; - color: #3f5167; - width: rem-calc(100px); - font-size: rem-calc(12px); - font-weight: 200; - border-color: #c4cdda; - border-radius: $global-radius; - } - input[type="text"] { - color: #7A8491; - } - - .search-results-container { - .no-results-item { - text-align: center; - } - } - - //Search Results - .search-results-list { - ul { - list-style-type: none; - text-align: center; - } - ul li { - display: inline-block; - padding-right: 5px; - } - .no-results-item { - list-style-type: none; - font-size: rem-calc(14px); - font-weight: normal; - } - .search-list-item { - background-color: white; - margin-bottom: rem-calc(10px);//5px 5px 5px 5px; - overflow-y: hidden; - font-weight: normal; - border: 1px solid #c4cdda; - border-radius: $global-radius; - - &:hover { - cursor: pointer; - } - - .logo { - width: 48px; - min-width: 48px; - height: 48px; - min-height: 48px; - padding: 10px; - background: $primary-color; - border-radius: $global-radius; - margin-left: rem-calc(10px); - margin-bottom: rem-calc(25px); - .d-logo { - color: $ghost; - font-size: rem-calc(32px); - margin: 0 auto; - } - } - - .search-item-avatar { - } - - .search-bar-details { - line-height: rem-calc(12px); - height: rem-calc(24px); - background-color: #c4cdda; - p { - font-weight: 300; - font-size: rem-calc(12px); - margin-bottom: 0; - line-height: 1.5rem; - } - } - - .search-item-basic-info { - .search-item-name { - font-size: 1.4rem; - font-weight: 600; - } - p { - font-size: 0.8rem; - } - .search-item-description { - font-size: rem-calc(12px); - } - } - - .search-item-other-info { - font-size: rem-calc(10px); - } - - .search-item-badges-stats { - ul li { - line-height: 0.6rem; - border-left: 1px solid #c4cdda; - } - p { - margin-bottom: 0; - font-size: rem-calc(12px); - font-weight: 500; - } - .search-item-badges { - } - .search-item-stats { - span { - padding-left: rem-calc(4px); - } - } - } - } - } -} - -.paging-bar { - display: inline-flex; - float: right; - margin-right: rem-calc(25px); - .paging-info { - align-self: center; - } - .paging-buttons { - align-self: center; - button { - margin: 0; - background-color: $body-bg; - color: $docker-dark; - padding-right: 0; - padding-left: rem-calc(4px); - box-shadow: none; - &:hover { - color: $primary-color; - box-shadow: none; - } - &:focus { - color: #7A8491; - outline: none; - box-shadow: none; - } - i { - font-size: 24; - } - } - button[disabled] { - opacity: 0.3; - box-shadow: none; - } - } -} - -.searchbar { - input[type=text] { - background: #69788a;/** need variable here **/ - border: 1px solid #4c5968;/** need variable here **/ - border-radius: $global-radius; - color: $white; - display: block; - height: 2rem; - padding: .2rem 2rem; - top: .6rem; - } - i.fa.fa-search { - color: #fff; - margin-top: -18px;/** lame **/ - margin-left: 11px;/** lame **/ - } -} - -// target webkit only meh -@media screen and (-webkit-min-device-pixel-ratio: 0) { - i.fa.fa-search { - margin-top: -16px!important;/** super lame, this can not be permanent **/ - } -} diff --git a/app/styles/hub/tabs.scss b/app/styles/hub/tabs.scss deleted file mode 100644 index ef90208ab0..0000000000 --- a/app/styles/hub/tabs.scss +++ /dev/null @@ -1,26 +0,0 @@ -.tabs { - position: relative; - float: left; - width: 100%; - li:first-child a { - border-top-left-radius: $global-radius; - } - li:last-child a { - border-top-right-radius: $global-radius; - border-right: 1px solid $docker-dark--placeholders; - } - a.repo-tab { - border-left: 1px solid $docker-dark--placeholders; - border-top: 1px solid $docker-dark--placeholders; - border-bottom: 1px solid $docker-dark--placeholders; - background:lighten($docker-dark--placeholders, 10%); - padding: .5rem 1.8rem; - font-size: 16px; - &.active { - border-bottom: 1px solid white; - background: white; - position: relative; - z-index: 2; - } - } -} diff --git a/app/styles/hub/usericons.scss b/app/styles/hub/usericons.scss deleted file mode 100644 index ca476b3191..0000000000 --- a/app/styles/hub/usericons.scss +++ /dev/null @@ -1,6 +0,0 @@ -.profile-photo { - width: rem-calc(24px); - height: rem-calc(24px); - margin-right: 5px; - border-radius: $global-radius; -} \ No newline at end of file diff --git a/app/styles/main.scss b/app/styles/main.scss deleted file mode 100644 index c7ee2ba6c6..0000000000 --- a/app/styles/main.scss +++ /dev/null @@ -1,170 +0,0 @@ -@import 'docker-ux'; -@import 'mono-blue'; -@import '_docker'; - -//============================REMOVE THIS====================================== - -$default-margin: 1.5rem; - -.flex-table { - display: flex; - flex-flow: column; - justify-content: center; - border: 1px solid $border-input; - border-radius: $global-radius; - font-size: 1rem; - margin: 0.5rem; - line-height: 1.5; - font-weight: 500; - color: $secondary-2; - .flex-row { - width: 100%; - display: flex; - border-bottom: 1px solid $secondary-5; - background: white; - &:last-child { - border-bottom: 0; - } - &.header { - background-color: $primary-1; - font-weight: 700; - color: white; - font-size: 1.2rem; - border-bottom: 0; - } - .flex-item { - display: flex; - flex-flow: row nowrap; - flex-grow: 1; - flex-basis: 0; - padding: 0.7em 1.2rem 0.7em 1.2rem; - word-break: break-word; - a { - color: $primary-1; - &:hover { - color: darken($primary-1, 10%); - } - } - } - } -} - -//============================================================================= - -@import 'hub'; - -.button { - // seems to feel unresponsive with almost any transition length - transition: 0.1s; - font-weight: 500; -} - -//TODO: could be global style -.create-object-btn { - background-color: white; - border: 4px dashed #c4cdda; - border-radius: $global-radius; - box-shadow: none; - color: $docker-dark; - line-height: 2.65rem; - margin: rem-calc(20px); - padding: 0.7rem; - font-size: large; - text-align: center; - width: 90%; - cursor: pointer; - &:hover { - background-color: $docker-light; - color: $docker-dark; - } - &:focus { - background-color: $docker-light; - color: $docker-dark; - } - i { - float: right; - } -} - -//TODO: could be global style -.blank-slate { - min-height: 600px; -} - -.page-top-header { - background-color: white; - h3 { - color: #22b8eb; - font-weight: 300; - } -} - -.temp-page { - margin-top: 2rem; - text-align: center; - h1 { - font-size: 24px; - font-weight: 300; - color: lighten(gray, 15%); - } -} - - - select { - background-color: transparent; - border: 1px solid #c4cdda; - transition: border-color 0.15s linear 0s, background 0.15s linear 0s; - outline: 0; - color: #3f5167; - width: rem-calc(100px); - font-size: rem-calc(14px); - font-weight: 300; - border-color: #c4cdda; - border-radius: $global-radius; - } - -form .row textarea.columns { - padding-left: 1rem; -} - -.global-select { - .text { - margin-right: 1rem; - color: $secondary-4; - } -} - -.alert-box { - border-radius: $global-radius; -} - -//TODO: fix in dux -.sk-cube { - background-color: #546473 !important; -} - -/* Pre-move to docker-ux */ -@import 'common/_secondary-top-bar'; -@import 'common/_repository-list-item'; - -// Don't kill me -.mktoForm { - margin-top: 10px; - select#Country { - margin-top: 20px; - } - #Phone { - margin-top: 20px; - } - #accept_eval_terms { - margin-top: 30px; - } -} -.mktoForm div.mktoFormRow { - padding-bottom: 20px; -} -.mktoFieldWrap { - label { - top: -15px; - } -} diff --git a/app/styles/vendor-overrides/rc-tooltip.css b/app/styles/vendor-overrides/rc-tooltip.css deleted file mode 100644 index ab6f60e661..0000000000 --- a/app/styles/vendor-overrides/rc-tooltip.css +++ /dev/null @@ -1,31 +0,0 @@ -.rc-tooltip-inner { - border: 0 none; - box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); -} -.rc-tooltip-placement-top .rc-tooltip-arrow { - border-left: 0 none; - border-top: 0 none; - background: #fff; - width: 10px; - height: 10px; - transform: rotate(45deg); - border-right: 1px solid #ddd; - border-bottom: 1px solid #ddd; - z-index: 999; -} - -.rc-tooltip-placement-bottom .rc-tooltip-arrow { - background: #fff; - width: 10px; - height: 10px; - transform: rotate(45deg); - border-right: 0 none; - border-bottom: 0 none; - border-left: 1px solid #ddd; - border-top: 1px solid #ddd; - z-index: 999; -} - -.rc-tooltip-inner * { - word-wrap: break-word; -} diff --git a/app/styles/vendor-overrides/react-select.css b/app/styles/vendor-overrides/react-select.css deleted file mode 100644 index dbce7cfccd..0000000000 --- a/app/styles/vendor-overrides/react-select.css +++ /dev/null @@ -1,279 +0,0 @@ -/** - * React Select - * ============ - * Created by Jed Watson and Joss Mackison for KeystoneJS, http://www.keystonejs.com/ - * https://twitter.com/jedwatson https://twitter.com/jossmackison https://twitter.com/keystonejs - * MIT License: https://github.com/keystonejs/react-select - * - * Modified to match our styles -*/ - -.Select { - position: relative; -} -.Select-control { - position: relative; - overflow: hidden; - background-color: #fff; - border: 1px solid #ccc; - border-color: #d9d9d9 #ccc #b3b3b3; - border-radius: 3px; - box-sizing: border-box; - color: #333; - cursor: default; - outline: none; - padding: 8px 52px 8px 10px; -} -.Select-control:hover { - box-shadow: 0 1px 0 rgba(0, 0, 0, 0.06); -} -.is-searchable.is-open > .Select-control { - cursor: text; -} -.is-open > .Select-control { - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; - background: #fff; - border-color: #b3b3b3 #ccc #d9d9d9; -} -.is-open > .Select-control > .Select-arrow { - border-color: transparent transparent #999; - border-width: 0 5px 5px; -} -.is-searchable.is-focused:not(.is-open) > .Select-control { - cursor: text; -} -.is-focused:not(.is-open) > .Select-control { - border-color: #08c #0099e6 #0099e6; - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 0 5px -1px rgba(0, 136, 204, 0.5); -} -.Select-placeholder { - color: #aaa; - padding: 4px 52px 8px 10px; - position: absolute; - top: 0; - left: 0; - right: -15px; - max-width: 100%; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} -.has-value > .Select-control > .Select-placeholder { - color: #333; -} -.Select-value { - color: #aaa; - padding: 4px 52px 8px 10px; - position: absolute; - top: 0; - left: 0; - right: -15px; - max-width: 100%; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} -.has-value > .Select-control > .Select-value { - color: #333; -} -.Select-input > input { - cursor: default; - background: none transparent; - box-shadow: none; - height: auto; - border: 0 none; - font-family: inherit; - font-size: inherit; - margin: 0; - padding: 0; - outline: none; - display: inline-block; - -webkit-appearance: none; -} -.is-focused .Select-input > input { - cursor: text; -} -.Select-control:not(.is-searchable) > .Select-input { - outline: none; -} -.Select-loading { - -webkit-animation: Select-animation-spin 400ms infinite linear; - -o-animation: Select-animation-spin 400ms infinite linear; - animation: Select-animation-spin 400ms infinite linear; - width: 16px; - height: 16px; - box-sizing: border-box; - border-radius: 50%; - border: 2px solid #ccc; - border-right-color: #333; - display: inline-block; - position: relative; - margin-top: -8px; - position: absolute; - right: 30px; - top: 50%; -} -.has-value > .Select-control > .Select-loading { - right: 46px; -} -.Select-clear { - color: #999; - cursor: pointer; - display: inline-block; - font-size: 12px; - padding: 6px 10px; - position: absolute; - right: 17px; - top: 0; -} -.Select-clear:hover { - color: #c0392b; -} -.Select-clear > span { - font-size: 0.8rem; -} -.Select-arrow-zone { - content: " "; - display: block; - position: absolute; - right: 0; - top: 0; - bottom: 0; - width: 30px; - cursor: pointer; -} -.Select-arrow { - border-color: #999 transparent transparent; - border-style: solid; - border-width: 5px 5px 0; - content: " "; - display: block; - height: 0; - margin-top: -ceil(2.5px); - position: absolute; - right: 10px; - top: 14px; - width: 0; - cursor: pointer; -} -.Select-menu-outer { - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; - background-color: #fff; - border: 1px solid #ccc; - border-top-color: #e6e6e6; - box-shadow: 0 1px 0 rgba(0, 0, 0, 0.06); - box-sizing: border-box; - margin-top: -1px; - max-height: 200px; - position: absolute; - top: 100%; - width: 100%; - z-index: 1000; - -webkit-overflow-scrolling: touch; -} -.Select-menu { - max-height: 198px; - overflow-y: auto; -} -.Select-option { - box-sizing: border-box; - color: #666666; - cursor: pointer; - display: block; - padding: 8px 10px; -} -.Select-option:last-child { - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; -} -.Select-option.is-focused { - background-color: #f2f9fc; - color: #333; -} -.Select-option.is-disabled { - color: #cccccc; - cursor: not-allowed; -} -.Select-noresults, -.Select-search-prompt, -.Select-searching { - box-sizing: border-box; - color: #999999; - cursor: default; - display: block; - padding: 8px 10px; -} -.Select.is-multi .Select-control { - padding: 2px 52px 2px 3px; -} -.Select.is-multi .Select-input { - vertical-align: middle; - border: 1px solid transparent; - margin: 2px; - padding: 3px 0; -} -.Select-item { - background-color: #f2f9fc; - border-radius: 2px; - border: 1px solid #c9e6f2; - color: #08c; - display: inline-block; - font-size: 0.8rem; - margin: 2px; -} -.Select-item-icon, -.Select-item-label { - display: inline-block; - vertical-align: middle; -} -.Select-item-label { - cursor: default; - border-bottom-right-radius: 2px; - border-top-right-radius: 2px; - padding: 3px 5px; -} -.Select-item-label .Select-item-label__a { - color: #08c; - cursor: pointer; -} -.Select-item-icon { - cursor: pointer; - border-bottom-left-radius: 2px; - border-top-left-radius: 2px; - border-right: 1px solid #c9e6f2; - padding: 2px 5px 4px; -} -.Select-item-icon:hover, -.Select-item-icon:focus { - background-color: #ddeff7; - color: #0077b3; -} -.Select-item-icon:active { - background-color: #c9e6f2; -} -.Select.is-multi.is-disabled .Select-item { - background-color: #f2f2f2; - border: 1px solid #d9d9d9; - color: #888; -} -.Select.is-multi.is-disabled .Select-item-icon { - cursor: not-allowed; - border-right: 1px solid #d9d9d9; -} -.Select.is-multi.is-disabled .Select-item-icon:hover, -.Select.is-multi.is-disabled .Select-item-icon:focus, -.Select.is-multi.is-disabled .Select-item-icon:active { - background-color: #f2f2f2; -} -@keyframes Select-animation-spin { - to { - transform: rotate(1turn); - } -} -@-webkit-keyframes Select-animation-spin { - to { - -webkit-transform: rotate(1turn); - } -} diff --git a/circle.yml b/circle.yml deleted file mode 100644 index 0de8e4850b..0000000000 --- a/circle.yml +++ /dev/null @@ -1,43 +0,0 @@ -machine: - pre: - - echo 'DOCKER_OPTS="-s btrfs -e lxc -D --userland-proxy=false"' | sudo tee -a /etc/default/docker - - sudo curl -L -o /usr/bin/docker 'https://s3-external-1.amazonaws.com/circle-downloads/docker-1.8.2-circleci-cp-workaround' - - sudo chmod 0755 /usr/bin/docker - node: - version: 4.1.0 - services: - - docker -dependencies: - override: - - mkdir -p ./bin - - pip install fabric==1.8.1 - - pip install pycrypto - - make hub-deps -test: - override: - - docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_AUTH - - docker build -f dockerfiles/milky-way-no-bin -t milky-no-bin ./dockerfiles - - make dev - - make dev-tag - - make stage - - mkdir .stage/ - - make copy-stage - - docker run -d --name milky milky-no-bin sleep 15m - - cd .stage/.build-prod && docker cp milky:/opt/hub/modules.tar . && docker build -t bagel/hub-stage . - - make prod - - make base-prod-tag - - make copy-prod - - docker run -d --name milky-2 milky-no-bin sleep 15m - - cd .build-prod && docker cp milky-2:/opt/hub/modules.tar . && docker build -t bagel/hub-prod . - - docker run -de ENV=production -p 3000:3000 --name hub-prod-tester bagel/hub-prod - - sleep 60s - - curl $(docker inspect --format '{{ .NetworkSettings.IPAddress }}' hub-prod-tester):3000 -deployment: - autodeploy: - branch: [master, autodeploy] - owner: docker - commands: - - docker push bagel/hub-prod - - docker push bagel/hub-stage - - chmod 400 ~/.ssh/id_console-demo - - fab -H root@console-demo.docker.com -i ~/.ssh/id_console-demo start_project:email=$DOCKER_EMAIL,user=$DOCKER_USER,auth=$DOCKER_AUTH,beta_password=$BETA_PASSWORD,sha=latest,new_relic_key=$NEW_RELIC_KEY,new_relic_app_name=$NEW_RELIC_APP_NAME diff --git a/containers/README.md b/containers/README.md deleted file mode 100644 index 6cb24e12b8..0000000000 --- a/containers/README.md +++ /dev/null @@ -1,48 +0,0 @@ - -# Containers - -These are the "accessory" containers with which Hub 2.0 is run. - -## dnsmasq - -dnsmasq is used to fake the `Origin` header in CORS requests. This is -necessary because the browser automatically sends `Origin: localhost` -(users can't modify it) and we need it to be in the `*.docker.com` -space, since staging is set up to handle single dot subdomains. - -We've chosen `bagels.docker.com` as the development domain (something -that is unlikely to ever be deployed in production so that we won't -have to change the name in the future). - -### prerequisites - -```bash -cd $PROJECT -make dns -``` - -This runs `$PROJECT/containers/configure_system_dns.sh`, which will -add `bagels.docker.com` to your host system's `/etc/resolver/`. This -makes it so that `bagels.docker.com` will resolver to `boot2docker ip`. - -### run - -```bash -cd $PROJECT/containers/dnsmasq -docker build -t bagelteam/dnsmasq -docker run -itp 53:53/udp bagelteam/dnsmasq -``` - -## HAProxy - -HAProxy is a load balancer used to terminate SSL. - -Currently Out-of-Order. - -```bash -docker run -itp 80:80 -p 443:433 bagelteam/haproxy -``` - -HAProxy will load balance `bagels.docker.com` across a single -container (hah), and more importantly, take care of SSL Offloading at -the load balancer. The image has it's own SSL certificates. diff --git a/containers/dnsmasq/Dockerfile b/containers/dnsmasq/Dockerfile deleted file mode 100644 index 40c00e83d5..0000000000 --- a/containers/dnsmasq/Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM debian:jessie - -MAINTAINER Chris Biscardi - -RUN apt-get update && apt-get install -y dnsmasq - -EXPOSE 53/udp - -ADD ./run /opt/run - -CMD "/opt/run" -# docker run -d -p 53:53/udp --name docker-dnsmasq dnsmasq --address=/dev.docker.io/172.16.200.100 diff --git a/containers/dnsmasq/configure_system_dns.sh b/containers/dnsmasq/configure_system_dns.sh deleted file mode 100755 index d84112198a..0000000000 --- a/containers/dnsmasq/configure_system_dns.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -# Docker Bridge IP - https://docs.docker.com/articles/networking/ -# $DOCKER_HOST will be the IP of the boot2docker or docker-machine -# instance *currently sourced in your shell*. This means something -# like $(docker-machine env dev) or $(boot2docker shellinit) -if [[ $DOCKER_HOST =~ ([0-9]{1,3}[\.]){3}[0-9]{1,3} ]]; then - DAEMON_IPV4=$BASH_REMATCH - echo $DAEMON_IPV4 -else - echo "unable to parse string $DOCKER_HOST" -fi - -set_dev_resolver() { - echo "Bagels need your permission to configure system DNS." - sudo mkdir -p /etc/resolver - echo "nameserver $DAEMON_IPV4" | sudo tee /etc/resolver/bagels.docker.com -} - -if [ ! -f /etc/resolver/bagels.docker.com ]; then - set_dev_resolver -elif [ "$(cat /etc/resolver/bagels.docker.com)" != "nameserver $DAEMON_IPV4" ]; then - set_dev_resolver -fi diff --git a/containers/dnsmasq/run b/containers/dnsmasq/run deleted file mode 100755 index b2b60ad240..0000000000 --- a/containers/dnsmasq/run +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -# match the ip address from a DOCKER_HOST which is set by boot2docker -# and docker-machine -if [[ $DOCKER_HOST =~ ([0-9]{1,3}[\.]){3}[0-9]{1,3} ]]; then - strresult=$BASH_REMATCH - echo $strresult -else - echo "unable to parse string $DOCKER_HOST" -fi - -/usr/sbin/dnsmasq -q --no-daemon --address=/bagels.docker.com/$strresult -#$strresult diff --git a/containers/haproxy/Dockerfile b/containers/haproxy/Dockerfile deleted file mode 100644 index 034260c7e2..0000000000 --- a/containers/haproxy/Dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM fish/haproxy - -ADD . /haproxy - -EXPOSE 80 443 - -# Check is haproxy.cfg is valid before we start -# CMD "(haproxy -c -f /haproxy/haproxy.cfg || ( echo 'Bad haproxy config'; exit; )) && /usr/sbin/haproxy -f /haproxy/haproxy.cfg & && wait $!" - -ENTRYPOINT ["/haproxy/run"] \ No newline at end of file diff --git a/containers/haproxy/haproxy.cfg b/containers/haproxy/haproxy.cfg deleted file mode 100644 index b9d1c5014a..0000000000 --- a/containers/haproxy/haproxy.cfg +++ /dev/null @@ -1,41 +0,0 @@ -global - chroot /var/lib/haproxy - user haproxy - group haproxy - -defaults - log global - mode http - option httplog - option dontlognull - timeout connect 5000 - timeout client 50000 - timeout server 50000 - errorfile 400 /etc/haproxy/errors/400.http - errorfile 403 /etc/haproxy/errors/403.http - errorfile 408 /etc/haproxy/errors/408.http - errorfile 500 /etc/haproxy/errors/500.http - errorfile 502 /etc/haproxy/errors/502.http - errorfile 503 /etc/haproxy/errors/503.http - errorfile 504 /etc/haproxy/errors/504.http - stats enable - stats auth haproxy:hapass - -frontend https - bind :443 ssl crt /haproxy/keys/bagels.docker.com/bagels.docker.pem - acl is-ssl dst_port 443 - - http-request set-header X-Real-IP %ci - - reqadd X-Forwarded-Proto:\ https if is-ssl - reqadd X-Forwarded-Port:\ 443 if is-ssl - rspadd Strict-Transport-Security:\ max-age=31536000 if is-ssl - - acl is_hub_dev hdr(host) -i bagels.docker.com - - use_backend hub_dev if is_hub_dev - -backend hub_dev - balance leastconn - option httpclose - server docker-1 {DOCKER_HOST}:7001 check \ No newline at end of file diff --git a/containers/haproxy/keys/bagels.docker.com/bagels.docker.crt b/containers/haproxy/keys/bagels.docker.com/bagels.docker.crt deleted file mode 100644 index 44765408fb..0000000000 --- a/containers/haproxy/keys/bagels.docker.com/bagels.docker.crt +++ /dev/null @@ -1,14 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICNTCCAZ4CCQDY33gN8y9BQzANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJV -UzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xDzANBgNVBAoT -BkRvY2tlcjEaMBgGA1UEAxMRYmFnZWxzLmRvY2tlci5jb20wHhcNMTUwMTIxMDM1 -NTEzWhcNMTYwMTIxMDM1NTEzWjBfMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex -FjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xDzANBgNVBAoTBkRvY2tlcjEaMBgGA1UE -AxMRYmFnZWxzLmRvY2tlci5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB -AMluBCvOUrdFkFGCmpKBPduoZgYE/hNKnmX3Cqrn+FsodOBiin1lOs7+XX3EY078 -u5QIULNZ3j/LUSuxgHBS8RcVc3ljCkvwRURwVy6FWunahdTULLEq+qOByv6Hq2/W -itlzT2Rw6Tu29IThb7Mtxb1B6LoAorkWX/YEXankpVPnAgMBAAEwDQYJKoZIhvcN -AQEFBQADgYEAPdqZ2jLxOuZ52wucJN1DoOBUCWnCM5bfBHOU3wBqSPA/mT2Bw5Fo -evqqd+mRWizgmSkDM9NpO9cj9tpeidTrHsTutkqjQttIeNAtZm82sSWH7ul1N1du -4aDDKwAk4j9BYPUmYQFaSRKNtE/OpGVPxxK/ZBS8YeVT0knzTr/a9to= ------END CERTIFICATE----- diff --git a/containers/haproxy/keys/bagels.docker.com/bagels.docker.csr b/containers/haproxy/keys/bagels.docker.com/bagels.docker.csr deleted file mode 100644 index b9d96abb7e..0000000000 --- a/containers/haproxy/keys/bagels.docker.com/bagels.docker.csr +++ /dev/null @@ -1,11 +0,0 @@ ------BEGIN CERTIFICATE REQUEST----- -MIIBnzCCAQgCAQAwXzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQH -Ew1TYW4gRnJhbmNpc2NvMQ8wDQYDVQQKEwZEb2NrZXIxGjAYBgNVBAMTEWJhZ2Vs -cy5kb2NrZXIuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJbgQrzlK3 -RZBRgpqSgT3bqGYGBP4TSp5l9wqq5/hbKHTgYop9ZTrO/l19xGNO/LuUCFCzWd4/ -y1ErsYBwUvEXFXN5YwpL8EVEcFcuhVrp2oXU1CyxKvqjgcr+h6tv1orZc09kcOk7 -tvSE4W+zLcW9Qei6AKK5Fl/2BF2p5KVT5wIDAQABoAAwDQYJKoZIhvcNAQEFBQAD -gYEAlAQKhy4j7wenWqnKzfpp/o0cbzQAcve76XSwfWrzONFDZidhQlwAKBdYbYN3 -4ITqNw4MPSCMBkMMCQFFFHM/+NqlAmYYbJHv8uDxKel/7IsxIEPRun0b6k/+wL2e -2nyJJrMwesVrzvDwfB+8eoUOZFJIiX6htpxU4vgq9xMgMAg= ------END CERTIFICATE REQUEST----- diff --git a/containers/haproxy/keys/bagels.docker.com/bagels.docker.key b/containers/haproxy/keys/bagels.docker.com/bagels.docker.key deleted file mode 100644 index 6659dc144c..0000000000 --- a/containers/haproxy/keys/bagels.docker.com/bagels.docker.key +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIICWwIBAAKBgQDJbgQrzlK3RZBRgpqSgT3bqGYGBP4TSp5l9wqq5/hbKHTgYop9 -ZTrO/l19xGNO/LuUCFCzWd4/y1ErsYBwUvEXFXN5YwpL8EVEcFcuhVrp2oXU1Cyx -Kvqjgcr+h6tv1orZc09kcOk7tvSE4W+zLcW9Qei6AKK5Fl/2BF2p5KVT5wIDAQAB -AoGAcA+Qqn5Cbkt5Gp+6Nr9IFqf8+mRUpY7hyIBDowkiljRPsXWg7loe+YFxqcJU -LWFVSenGW8Enb/5AzjoV5md+UAiERbF13SzrEx7J7riwb1ljHe82RqUbyfpnnDWT -aSZ/ce+9LYoYggFVfH7DloT8NNsQzTDi2/g+66dXi8fcIIECQQDqykIcF20sz8Ar -H3StlgITEorJiZRpvbzuQ6G7XoC1XOI1/0+1NbIHm3lv4XfvaRSdKv0mnPaZmi3h -PWZC/zj3AkEA26BE6iEGO3eJ39l1zRpB1jS/VrEAa7pzGeEFeL+k/5XEWqsgHOtQ -qIbPtCyKcN5mtCYEg6GEK/pqNALWL6ZwkQJATT9CRO/IMaggd4+f2cSy5geBthEX -zTppwJJr0bOj8QegPVfEp8AE1M/oQlESHqiZ6aPNKjkWQS8izSpgTMafvQJAILDT -cTInNlTNvfcldLkS0aqaTHIeSOrA1TpMUTPdgHmvd3t/VS6lm+AtLHlwxeokyW3b -QCibftxQUJuXfBI/MQJAAt2m8P0V+U/MFjNhYUd2jwJIFFh7AVYeSH26NxzQMgO0 -YNQAaRKxwuhDrxyVwezryzyBcVWKdfhCtgOK6U5mFw== ------END RSA PRIVATE KEY----- diff --git a/containers/haproxy/keys/bagels.docker.com/bagels.docker.pem b/containers/haproxy/keys/bagels.docker.com/bagels.docker.pem deleted file mode 100644 index 753429af60..0000000000 --- a/containers/haproxy/keys/bagels.docker.com/bagels.docker.pem +++ /dev/null @@ -1,29 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICNTCCAZ4CCQDY33gN8y9BQzANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJV -UzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xDzANBgNVBAoT -BkRvY2tlcjEaMBgGA1UEAxMRYmFnZWxzLmRvY2tlci5jb20wHhcNMTUwMTIxMDM1 -NTEzWhcNMTYwMTIxMDM1NTEzWjBfMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex -FjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xDzANBgNVBAoTBkRvY2tlcjEaMBgGA1UE -AxMRYmFnZWxzLmRvY2tlci5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB -AMluBCvOUrdFkFGCmpKBPduoZgYE/hNKnmX3Cqrn+FsodOBiin1lOs7+XX3EY078 -u5QIULNZ3j/LUSuxgHBS8RcVc3ljCkvwRURwVy6FWunahdTULLEq+qOByv6Hq2/W -itlzT2Rw6Tu29IThb7Mtxb1B6LoAorkWX/YEXankpVPnAgMBAAEwDQYJKoZIhvcN -AQEFBQADgYEAPdqZ2jLxOuZ52wucJN1DoOBUCWnCM5bfBHOU3wBqSPA/mT2Bw5Fo -evqqd+mRWizgmSkDM9NpO9cj9tpeidTrHsTutkqjQttIeNAtZm82sSWH7ul1N1du -4aDDKwAk4j9BYPUmYQFaSRKNtE/OpGVPxxK/ZBS8YeVT0knzTr/a9to= ------END CERTIFICATE----- ------BEGIN RSA PRIVATE KEY----- -MIICWwIBAAKBgQDJbgQrzlK3RZBRgpqSgT3bqGYGBP4TSp5l9wqq5/hbKHTgYop9 -ZTrO/l19xGNO/LuUCFCzWd4/y1ErsYBwUvEXFXN5YwpL8EVEcFcuhVrp2oXU1Cyx -Kvqjgcr+h6tv1orZc09kcOk7tvSE4W+zLcW9Qei6AKK5Fl/2BF2p5KVT5wIDAQAB -AoGAcA+Qqn5Cbkt5Gp+6Nr9IFqf8+mRUpY7hyIBDowkiljRPsXWg7loe+YFxqcJU -LWFVSenGW8Enb/5AzjoV5md+UAiERbF13SzrEx7J7riwb1ljHe82RqUbyfpnnDWT -aSZ/ce+9LYoYggFVfH7DloT8NNsQzTDi2/g+66dXi8fcIIECQQDqykIcF20sz8Ar -H3StlgITEorJiZRpvbzuQ6G7XoC1XOI1/0+1NbIHm3lv4XfvaRSdKv0mnPaZmi3h -PWZC/zj3AkEA26BE6iEGO3eJ39l1zRpB1jS/VrEAa7pzGeEFeL+k/5XEWqsgHOtQ -qIbPtCyKcN5mtCYEg6GEK/pqNALWL6ZwkQJATT9CRO/IMaggd4+f2cSy5geBthEX -zTppwJJr0bOj8QegPVfEp8AE1M/oQlESHqiZ6aPNKjkWQS8izSpgTMafvQJAILDT -cTInNlTNvfcldLkS0aqaTHIeSOrA1TpMUTPdgHmvd3t/VS6lm+AtLHlwxeokyW3b -QCibftxQUJuXfBI/MQJAAt2m8P0V+U/MFjNhYUd2jwJIFFh7AVYeSH26NxzQMgO0 -YNQAaRKxwuhDrxyVwezryzyBcVWKdfhCtgOK6U5mFw== ------END RSA PRIVATE KEY----- diff --git a/containers/haproxy/run b/containers/haproxy/run deleted file mode 100755 index b26edf0b91..0000000000 --- a/containers/haproxy/run +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -# match the ip address from a DOCKER_HOST which is set by boot2docker -# and docker-machine -if [[ $DOCKER_HOST =~ ([0-9]{1,3}[\.]){3}[0-9]{1,3} ]]; then - strresult=$BASH_REMATCH - echo $strresult -else - echo "unable to parse string $DOCKER_HOST" -fi - -sed -i s/{DOCKER_HOST}/"$strresult"/g /haproxy/haproxy.cfg - -# Check is haproxy.cfg is valid before we start -haproxy -c -f /haproxy/haproxy.cfg || ( echo 'Bad haproxy config'; exit; ) - -/usr/sbin/haproxy -f /haproxy/haproxy.cfg & - -wait $! diff --git a/containers/prod/build b/containers/prod/build deleted file mode 100755 index af29f19d61..0000000000 --- a/containers/prod/build +++ /dev/null @@ -1 +0,0 @@ -docker build -t bagel/haproxy_beta ./haproxy \ No newline at end of file diff --git a/containers/prod/docker-compose.yml b/containers/prod/docker-compose.yml deleted file mode 100644 index 838d385d12..0000000000 --- a/containers/prod/docker-compose.yml +++ /dev/null @@ -1,13 +0,0 @@ -haproxy: - build: ./haproxy - ports: - - "80:80" - - "443:443" -hub: - build: bagelteam/hubtest - volumes: - - .:/opt/hub - ports: - - "7001:3000" - environment: - ENV: production \ No newline at end of file diff --git a/containers/prod/haproxy/Dockerfile b/containers/prod/haproxy/Dockerfile deleted file mode 100644 index 12a913f9de..0000000000 --- a/containers/prod/haproxy/Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -FROM fish/haproxy - -ADD ./haproxy.cfg /haproxy/haproxy.cfg -ADD ./run /haproxy/run - -EXPOSE 80 443 - -ENTRYPOINT ["/haproxy/run"] - diff --git a/containers/prod/haproxy/haproxy.cfg b/containers/prod/haproxy/haproxy.cfg deleted file mode 100644 index 72a144b20e..0000000000 --- a/containers/prod/haproxy/haproxy.cfg +++ /dev/null @@ -1,46 +0,0 @@ -global - chroot /var/lib/haproxy - user haproxy - group haproxy - -defaults - log global - mode http - option httplog - option dontlognull - timeout connect 5000 - timeout client 50000 - timeout server 50000 - errorfile 400 /etc/haproxy/errors/400.http - errorfile 403 /etc/haproxy/errors/403.http - errorfile 408 /etc/haproxy/errors/408.http - errorfile 500 /etc/haproxy/errors/500.http - errorfile 502 /etc/haproxy/errors/502.http - errorfile 503 /etc/haproxy/errors/503.http - errorfile 504 /etc/haproxy/errors/504.http - stats enable - stats auth haproxy:hapass - -userlist Bagels - user betalist insecure-password {BETA_PASSWORD} - -frontend https - bind :443 ssl crt /haproxy/keys/hub-beta.docker.com/hub-beta.docker.pem - acl is-ssl dst_port 443 - acl Auth_Bagels http_auth(Bagels) - http-request auth realm HubBeta if !Auth_Bagels - - http-request set-header X-Real-IP %ci - - reqadd X-Forwarded-Proto:\ https if is-ssl - reqadd X-Forwarded-Port:\ 443 if is-ssl - rspadd Strict-Transport-Security:\ max-age=31536000 if is-ssl - - acl is_hub_dev hdr(host) -i hub-beta.docker.com - - use_backend hub_dev if is_hub_dev - -backend hub_dev - balance leastconn - option httpclose - server docker-1 172.17.42.1:7001 check diff --git a/containers/prod/haproxy/keys/bagels.docker.com/bagels.docker.crt b/containers/prod/haproxy/keys/bagels.docker.com/bagels.docker.crt deleted file mode 100644 index 44765408fb..0000000000 --- a/containers/prod/haproxy/keys/bagels.docker.com/bagels.docker.crt +++ /dev/null @@ -1,14 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICNTCCAZ4CCQDY33gN8y9BQzANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJV -UzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xDzANBgNVBAoT -BkRvY2tlcjEaMBgGA1UEAxMRYmFnZWxzLmRvY2tlci5jb20wHhcNMTUwMTIxMDM1 -NTEzWhcNMTYwMTIxMDM1NTEzWjBfMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex -FjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xDzANBgNVBAoTBkRvY2tlcjEaMBgGA1UE -AxMRYmFnZWxzLmRvY2tlci5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB -AMluBCvOUrdFkFGCmpKBPduoZgYE/hNKnmX3Cqrn+FsodOBiin1lOs7+XX3EY078 -u5QIULNZ3j/LUSuxgHBS8RcVc3ljCkvwRURwVy6FWunahdTULLEq+qOByv6Hq2/W -itlzT2Rw6Tu29IThb7Mtxb1B6LoAorkWX/YEXankpVPnAgMBAAEwDQYJKoZIhvcN -AQEFBQADgYEAPdqZ2jLxOuZ52wucJN1DoOBUCWnCM5bfBHOU3wBqSPA/mT2Bw5Fo -evqqd+mRWizgmSkDM9NpO9cj9tpeidTrHsTutkqjQttIeNAtZm82sSWH7ul1N1du -4aDDKwAk4j9BYPUmYQFaSRKNtE/OpGVPxxK/ZBS8YeVT0knzTr/a9to= ------END CERTIFICATE----- diff --git a/containers/prod/haproxy/keys/bagels.docker.com/bagels.docker.csr b/containers/prod/haproxy/keys/bagels.docker.com/bagels.docker.csr deleted file mode 100644 index b9d96abb7e..0000000000 --- a/containers/prod/haproxy/keys/bagels.docker.com/bagels.docker.csr +++ /dev/null @@ -1,11 +0,0 @@ ------BEGIN CERTIFICATE REQUEST----- -MIIBnzCCAQgCAQAwXzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQH -Ew1TYW4gRnJhbmNpc2NvMQ8wDQYDVQQKEwZEb2NrZXIxGjAYBgNVBAMTEWJhZ2Vs -cy5kb2NrZXIuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJbgQrzlK3 -RZBRgpqSgT3bqGYGBP4TSp5l9wqq5/hbKHTgYop9ZTrO/l19xGNO/LuUCFCzWd4/ -y1ErsYBwUvEXFXN5YwpL8EVEcFcuhVrp2oXU1CyxKvqjgcr+h6tv1orZc09kcOk7 -tvSE4W+zLcW9Qei6AKK5Fl/2BF2p5KVT5wIDAQABoAAwDQYJKoZIhvcNAQEFBQAD -gYEAlAQKhy4j7wenWqnKzfpp/o0cbzQAcve76XSwfWrzONFDZidhQlwAKBdYbYN3 -4ITqNw4MPSCMBkMMCQFFFHM/+NqlAmYYbJHv8uDxKel/7IsxIEPRun0b6k/+wL2e -2nyJJrMwesVrzvDwfB+8eoUOZFJIiX6htpxU4vgq9xMgMAg= ------END CERTIFICATE REQUEST----- diff --git a/containers/prod/haproxy/keys/bagels.docker.com/bagels.docker.key b/containers/prod/haproxy/keys/bagels.docker.com/bagels.docker.key deleted file mode 100644 index 6659dc144c..0000000000 --- a/containers/prod/haproxy/keys/bagels.docker.com/bagels.docker.key +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIICWwIBAAKBgQDJbgQrzlK3RZBRgpqSgT3bqGYGBP4TSp5l9wqq5/hbKHTgYop9 -ZTrO/l19xGNO/LuUCFCzWd4/y1ErsYBwUvEXFXN5YwpL8EVEcFcuhVrp2oXU1Cyx -Kvqjgcr+h6tv1orZc09kcOk7tvSE4W+zLcW9Qei6AKK5Fl/2BF2p5KVT5wIDAQAB -AoGAcA+Qqn5Cbkt5Gp+6Nr9IFqf8+mRUpY7hyIBDowkiljRPsXWg7loe+YFxqcJU -LWFVSenGW8Enb/5AzjoV5md+UAiERbF13SzrEx7J7riwb1ljHe82RqUbyfpnnDWT -aSZ/ce+9LYoYggFVfH7DloT8NNsQzTDi2/g+66dXi8fcIIECQQDqykIcF20sz8Ar -H3StlgITEorJiZRpvbzuQ6G7XoC1XOI1/0+1NbIHm3lv4XfvaRSdKv0mnPaZmi3h -PWZC/zj3AkEA26BE6iEGO3eJ39l1zRpB1jS/VrEAa7pzGeEFeL+k/5XEWqsgHOtQ -qIbPtCyKcN5mtCYEg6GEK/pqNALWL6ZwkQJATT9CRO/IMaggd4+f2cSy5geBthEX -zTppwJJr0bOj8QegPVfEp8AE1M/oQlESHqiZ6aPNKjkWQS8izSpgTMafvQJAILDT -cTInNlTNvfcldLkS0aqaTHIeSOrA1TpMUTPdgHmvd3t/VS6lm+AtLHlwxeokyW3b -QCibftxQUJuXfBI/MQJAAt2m8P0V+U/MFjNhYUd2jwJIFFh7AVYeSH26NxzQMgO0 -YNQAaRKxwuhDrxyVwezryzyBcVWKdfhCtgOK6U5mFw== ------END RSA PRIVATE KEY----- diff --git a/containers/prod/haproxy/keys/bagels.docker.com/bagels.docker.pem b/containers/prod/haproxy/keys/bagels.docker.com/bagels.docker.pem deleted file mode 100644 index 753429af60..0000000000 --- a/containers/prod/haproxy/keys/bagels.docker.com/bagels.docker.pem +++ /dev/null @@ -1,29 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICNTCCAZ4CCQDY33gN8y9BQzANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJV -UzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xDzANBgNVBAoT -BkRvY2tlcjEaMBgGA1UEAxMRYmFnZWxzLmRvY2tlci5jb20wHhcNMTUwMTIxMDM1 -NTEzWhcNMTYwMTIxMDM1NTEzWjBfMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex -FjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xDzANBgNVBAoTBkRvY2tlcjEaMBgGA1UE -AxMRYmFnZWxzLmRvY2tlci5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB -AMluBCvOUrdFkFGCmpKBPduoZgYE/hNKnmX3Cqrn+FsodOBiin1lOs7+XX3EY078 -u5QIULNZ3j/LUSuxgHBS8RcVc3ljCkvwRURwVy6FWunahdTULLEq+qOByv6Hq2/W -itlzT2Rw6Tu29IThb7Mtxb1B6LoAorkWX/YEXankpVPnAgMBAAEwDQYJKoZIhvcN -AQEFBQADgYEAPdqZ2jLxOuZ52wucJN1DoOBUCWnCM5bfBHOU3wBqSPA/mT2Bw5Fo -evqqd+mRWizgmSkDM9NpO9cj9tpeidTrHsTutkqjQttIeNAtZm82sSWH7ul1N1du -4aDDKwAk4j9BYPUmYQFaSRKNtE/OpGVPxxK/ZBS8YeVT0knzTr/a9to= ------END CERTIFICATE----- ------BEGIN RSA PRIVATE KEY----- -MIICWwIBAAKBgQDJbgQrzlK3RZBRgpqSgT3bqGYGBP4TSp5l9wqq5/hbKHTgYop9 -ZTrO/l19xGNO/LuUCFCzWd4/y1ErsYBwUvEXFXN5YwpL8EVEcFcuhVrp2oXU1Cyx -Kvqjgcr+h6tv1orZc09kcOk7tvSE4W+zLcW9Qei6AKK5Fl/2BF2p5KVT5wIDAQAB -AoGAcA+Qqn5Cbkt5Gp+6Nr9IFqf8+mRUpY7hyIBDowkiljRPsXWg7loe+YFxqcJU -LWFVSenGW8Enb/5AzjoV5md+UAiERbF13SzrEx7J7riwb1ljHe82RqUbyfpnnDWT -aSZ/ce+9LYoYggFVfH7DloT8NNsQzTDi2/g+66dXi8fcIIECQQDqykIcF20sz8Ar -H3StlgITEorJiZRpvbzuQ6G7XoC1XOI1/0+1NbIHm3lv4XfvaRSdKv0mnPaZmi3h -PWZC/zj3AkEA26BE6iEGO3eJ39l1zRpB1jS/VrEAa7pzGeEFeL+k/5XEWqsgHOtQ -qIbPtCyKcN5mtCYEg6GEK/pqNALWL6ZwkQJATT9CRO/IMaggd4+f2cSy5geBthEX -zTppwJJr0bOj8QegPVfEp8AE1M/oQlESHqiZ6aPNKjkWQS8izSpgTMafvQJAILDT -cTInNlTNvfcldLkS0aqaTHIeSOrA1TpMUTPdgHmvd3t/VS6lm+AtLHlwxeokyW3b -QCibftxQUJuXfBI/MQJAAt2m8P0V+U/MFjNhYUd2jwJIFFh7AVYeSH26NxzQMgO0 -YNQAaRKxwuhDrxyVwezryzyBcVWKdfhCtgOK6U5mFw== ------END RSA PRIVATE KEY----- diff --git a/containers/prod/haproxy/run b/containers/prod/haproxy/run deleted file mode 100755 index 145832a4d5..0000000000 --- a/containers/prod/haproxy/run +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -sed -i s/{BETA_PASSWORD}/"$BETA_PASSWORD"/g /haproxy/haproxy.cfg - -# Check is haproxy.cfg is valid before we start -haproxy -c -f /haproxy/haproxy.cfg || ( echo 'Bad haproxy config'; exit; ) - -/usr/sbin/haproxy -f /haproxy/haproxy.cfg & - -wait $! diff --git a/deployment/deploy.sh b/deployment/deploy.sh deleted file mode 100755 index 9eded10710..0000000000 --- a/deployment/deploy.sh +++ /dev/null @@ -1,171 +0,0 @@ -#!/bin/sh - -DOCKER_CMD=docker - -alias AWS_HUB_PROD='aws ec2 describe-instances --filters "Name=tag:aws:cloudformation:stack-name,Values=us-east-1*" "Name=tag:secondary-role,Values=hub" "Name=instance-state-name,Values=running" --output=json' -alias AWS_HUB_STAGE='aws ec2 describe-instances --filters "Name=tag:aws:cloudformation:stack-name,Values=stage-us-east-1*" "Name=tag:secondary-role,Values=hub" "Name=instance-state-name,Values=running" --output=json' -alias AWS_IP="jq -r '.Reservations[].Instances[].PrivateIpAddress'" - -HUB_GATEWAY="https://hub.docker.com" -HUB_SERVICE_NAME="hub-web-v2" - -DEFAULT_IMAGE_PROD="bagel/hub-prod" -DEFAULT_IMAGE_STAGE="bagel/hub-stage" - -NEW_RELIC_APP_NAME="hub.docker.com(aws-node)" -NEW_RELIC_LICENSE_KEY="582e3891446a63a3f99b4d32f9585ec74af1d8d7" - -NO_COLOR="\033[0m" -RED="\033[0;31m" -GREEN="\033[0;32m" -YELLOW="\033[0;33m" - -MESSAGE_MISSING_OR_INVALID_ARGS="${RED}Missing or invalid arguments${NO_COLOR}" - -# $1: prod or stage -getAWSHosts() { - if [ $1 == "prod" ]; then - echo $(AWS_HUB_PROD | ( AWS_IP ; echo ) | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/:2376 /g') - elif [ $1 == "stage" ]; then - echo $(AWS_HUB_STAGE | ( AWS_IP ; echo ) | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/:2376 /g') - fi -} - -# $1: Exit code -printUsageAndExit() { - echo - echo "Usage: deploy.sh [prod|stage|-h ] [IMAGE]" - echo - echo " prod A predefined list of hosts for production" - echo " stage A predefined list of hosts for staging" - echo " -h A single host address" - echo - exit $1 -} - -# $1: Image argument -parseImageArg() { - if [ -z "$1" ]; then - echo $MESSAGE_MISSING_OR_INVALID_ARGS - printUsageAndExit 1 - fi - IMAGE=$1 -} - -parseArgs() { - if [ $1 == "-h" ]; then - parseImageArg $3 - HOSTS=$2 - else - if [ $1 == "prod" ]; then - if [ -z "$2" ]; then - IMAGE=$DEFAULT_IMAGE_PROD - else - parseImageArg $2 - fi - HOSTS=$( getAWSHosts "prod" ) - elif [ $1 == "stage" ]; then - if [ -z "$2" ]; then - IMAGE=$DEFAULT_IMAGE_STAGE - else - parseImageArg $2 - fi - HOSTS=$( getAWSHosts "stage" ) - else - echo - echo $MESSAGE_MISSING_OR_INVALID_ARGS - printUsageAndExit 1 - fi - fi -} - -# $1: Host IP -# $2: Image -# $3: Container name -# $4: Container port -runContainer() { - $DOCKER_CMD --tlsverify=false -H tcp://$1 run \ - -de ENV=production \ - -e HUB_API_BASE_URL=$HUB_GATEWAY \ - -e REGISTRY_API_BASE_URL=$HUB_GATEWAY \ - -e SERVICE_NAME=$HUB_SERVICE_NAME \ - -e SERVICE_80_NAME=$HUB_SERVICE_NAME \ - -e NEW_RELIC_LICENSE_KEY=$NEW_RELIC_LICENSE_KEY \ - -e NEW_RELIC_APP_NAME=$NEW_RELIC_APP_NAME \ - -e PORT=80 \ - -p $4:80 \ - --restart "unless-stopped" \ - --name $3 \ - $2 -} - -# $1: Host IP -# $2: Container name -removeContainer() { - $DOCKER_CMD --tlsverify=false -H tcp://$1 stop $2 - $DOCKER_CMD --tlsverify=false -H tcp://$1 rm $2 -} - -# $1: Host IP -# $2: Image name -pullImage() { - $DOCKER_CMD --tlsverify=false -H tcp://$1 pull $2 -} - -# $1: Host IP -# $2: Image -deployHost() { - echo - echo "Starting to deploy ${YELLOW}$IMAGE${NO_COLOR} to ${YELLOW}$1${NO_COLOR}" - - pullImage $1 $2 - - removeContainer $1 "hub_2_0" - runContainer $1 $2 "hub_2_0" 6600 - - removeContainer $1 "hub_2_1" - runContainer $1 $2 "hub_2_1" 6601 - - removeContainer $1 "hub_2_2" - runContainer $1 $2 "hub_2_2" 6602 -} - -# Prerequisites: -# 1- AWS -type aws >/dev/null 2>&1 || { echo >&2 "AWS client is required. Make sure 'aws' command is available:\nhttp://docs.aws.amazon.com/cli/latest/userguide/installing.html"; exit 1; } -# 2- JQ -type jq >/dev/null 2>&1 || { echo >&2 "jq JSON processor is required. Make sure 'jq' command is available:\nbrew install jq"; exit 1; } - -# Case for no paremeters specified -if [ -z "$1" ] - then - echo - echo $MESSAGE_MISSING_OR_INVALID_ARGS - printUsageAndExit 1 -fi - -parseArgs "$@" - -echo -echo "Image: ${YELLOW}$IMAGE ${NO_COLOR}" -echo "Hosts: ${YELLOW}$HOSTS${NO_COLOR}" -echo -read -p "Do you want to proceed? [Y/n]" -s -n 1 KEY -echo -if [[ ! $KEY =~ ^[Yy]$ ]]; then - exit 1 -fi - -# Run deployment for each host -for HUB_HOST in $HOSTS -do - deployHost $HUB_HOST $IMAGE - echo - echo "Sleeping for 10 seconds to let the containers boot up..." - echo - sleep 10 -done - -echo -echo "${GREEN}All done!${NO_COLOR}" -echo diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index c1257d728f..0000000000 --- a/docker-compose.yml +++ /dev/null @@ -1,28 +0,0 @@ -dnsmasq: - build: ./containers/dnsmasq - ports: - - "53:53/udp" - environment: - - DOCKER_HOST -haproxy: - build: ./containers/haproxy - environment: - - DOCKER_HOST - ports: - - "80:80" - - "443:443" -hub: - build: . - command: node --harmony ./server.js - working_dir: /opt/hub/app/.build - volumes: - - .:/opt/hub - - ./private-deps/docker-ux:/opt/node_modules/docker-ux - - ./private-deps/hub-js-sdk:/opt/node_modules/hub-js-sdk - ports: - - "7001:3000" - environment: - DEBUG: "hub:*" - HUB_API_BASE_URL: "https://hub-beta-stage.docker.com" - REGISTRY_API_BASE_URL: "https://hub-beta-stage.docker.com" - ENV: development diff --git a/docs/Dockerfile b/docker-hub/Dockerfile similarity index 100% rename from docs/Dockerfile rename to docker-hub/Dockerfile diff --git a/docs/Makefile b/docker-hub/Makefile similarity index 100% rename from docs/Makefile rename to docker-hub/Makefile diff --git a/docs/accounts.md b/docker-hub/accounts.md similarity index 100% rename from docs/accounts.md rename to docker-hub/accounts.md diff --git a/docs/bitbucket.md b/docker-hub/bitbucket.md similarity index 100% rename from docs/bitbucket.md rename to docker-hub/bitbucket.md diff --git a/docs/builds.md b/docker-hub/builds.md similarity index 100% rename from docs/builds.md rename to docker-hub/builds.md diff --git a/docs/github.md b/docker-hub/github.md similarity index 100% rename from docs/github.md rename to docker-hub/github.md diff --git a/docs/images/add-authorized-github-service.png b/docker-hub/images/add-authorized-github-service.png similarity index 100% rename from docs/images/add-authorized-github-service.png rename to docker-hub/images/add-authorized-github-service.png diff --git a/docs/images/authorized-services.png b/docker-hub/images/authorized-services.png similarity index 100% rename from docs/images/authorized-services.png rename to docker-hub/images/authorized-services.png diff --git a/docs/images/bitbucket-hook.png b/docker-hub/images/bitbucket-hook.png similarity index 100% rename from docs/images/bitbucket-hook.png rename to docker-hub/images/bitbucket-hook.png diff --git a/docs/images/bitbucket_creds.png b/docker-hub/images/bitbucket_creds.png similarity index 100% rename from docs/images/bitbucket_creds.png rename to docker-hub/images/bitbucket_creds.png diff --git a/docs/images/build-by.png b/docker-hub/images/build-by.png similarity index 100% rename from docs/images/build-by.png rename to docker-hub/images/build-by.png diff --git a/docs/images/build-states-ex.png b/docker-hub/images/build-states-ex.png similarity index 100% rename from docs/images/build-states-ex.png rename to docker-hub/images/build-states-ex.png diff --git a/docs/images/build-trigger.png b/docker-hub/images/build-trigger.png similarity index 100% rename from docs/images/build-trigger.png rename to docker-hub/images/build-trigger.png diff --git a/docs/images/busybox-image-tags.png b/docker-hub/images/busybox-image-tags.png similarity index 100% rename from docs/images/busybox-image-tags.png rename to docker-hub/images/busybox-image-tags.png diff --git a/docs/images/create-dialog.png b/docker-hub/images/create-dialog.png similarity index 100% rename from docs/images/create-dialog.png rename to docker-hub/images/create-dialog.png diff --git a/docs/images/create-dialog1.png b/docker-hub/images/create-dialog1.png similarity index 100% rename from docs/images/create-dialog1.png rename to docker-hub/images/create-dialog1.png diff --git a/docs/images/dashboard.png b/docker-hub/images/dashboard.png similarity index 100% rename from docs/images/dashboard.png rename to docker-hub/images/dashboard.png diff --git a/docs/images/deploy_key.png b/docker-hub/images/deploy_key.png similarity index 100% rename from docs/images/deploy_key.png rename to docker-hub/images/deploy_key.png diff --git a/docs/images/docker-integration.png b/docker-hub/images/docker-integration.png similarity index 100% rename from docs/images/docker-integration.png rename to docker-hub/images/docker-integration.png diff --git a/docs/images/first_pending.png b/docker-hub/images/first_pending.png similarity index 100% rename from docs/images/first_pending.png rename to docker-hub/images/first_pending.png diff --git a/docs/images/getting-started.png b/docker-hub/images/getting-started.png similarity index 100% rename from docs/images/getting-started.png rename to docker-hub/images/getting-started.png diff --git a/docs/images/gh-check-admin-org-dh-app-access.png b/docker-hub/images/gh-check-admin-org-dh-app-access.png similarity index 100% rename from docs/images/gh-check-admin-org-dh-app-access.png rename to docker-hub/images/gh-check-admin-org-dh-app-access.png diff --git a/docs/images/gh-check-user-org-dh-app-access.png b/docker-hub/images/gh-check-user-org-dh-app-access.png similarity index 100% rename from docs/images/gh-check-user-org-dh-app-access.png rename to docker-hub/images/gh-check-user-org-dh-app-access.png diff --git a/docs/images/gh_add_ssh_user_key.png b/docker-hub/images/gh_add_ssh_user_key.png similarity index 100% rename from docs/images/gh_add_ssh_user_key.png rename to docker-hub/images/gh_add_ssh_user_key.png diff --git a/docs/images/gh_docker-service.png b/docker-hub/images/gh_docker-service.png similarity index 100% rename from docs/images/gh_docker-service.png rename to docker-hub/images/gh_docker-service.png diff --git a/docs/images/gh_menu.png b/docker-hub/images/gh_menu.png similarity index 100% rename from docs/images/gh_menu.png rename to docker-hub/images/gh_menu.png diff --git a/docs/images/gh_org_members.png b/docker-hub/images/gh_org_members.png similarity index 100% rename from docs/images/gh_org_members.png rename to docker-hub/images/gh_org_members.png diff --git a/docs/images/gh_repo_deploy_key.png b/docker-hub/images/gh_repo_deploy_key.png similarity index 100% rename from docs/images/gh_repo_deploy_key.png rename to docker-hub/images/gh_repo_deploy_key.png diff --git a/docs/images/gh_service_hook.png b/docker-hub/images/gh_service_hook.png similarity index 100% rename from docs/images/gh_service_hook.png rename to docker-hub/images/gh_service_hook.png diff --git a/docs/images/gh_settings.png b/docker-hub/images/gh_settings.png similarity index 100% rename from docs/images/gh_settings.png rename to docker-hub/images/gh_settings.png diff --git a/docs/images/gh_team_members.png b/docker-hub/images/gh_team_members.png similarity index 100% rename from docs/images/gh_team_members.png rename to docker-hub/images/gh_team_members.png diff --git a/docs/images/github-side-hook.png b/docker-hub/images/github-side-hook.png similarity index 100% rename from docs/images/github-side-hook.png rename to docker-hub/images/github-side-hook.png diff --git a/docs/images/groups.png b/docker-hub/images/groups.png similarity index 100% rename from docs/images/groups.png rename to docker-hub/images/groups.png diff --git a/docs/images/home-page.png b/docker-hub/images/home-page.png similarity index 100% rename from docs/images/home-page.png rename to docker-hub/images/home-page.png diff --git a/docs/images/hub.png b/docker-hub/images/hub.png similarity index 100% rename from docs/images/hub.png rename to docker-hub/images/hub.png diff --git a/docs/images/invite.png b/docker-hub/images/invite.png similarity index 100% rename from docs/images/invite.png rename to docker-hub/images/invite.png diff --git a/docs/images/linked-acct.png b/docker-hub/images/linked-acct.png similarity index 100% rename from docs/images/linked-acct.png rename to docker-hub/images/linked-acct.png diff --git a/docs/images/login-web.png b/docker-hub/images/login-web.png similarity index 100% rename from docs/images/login-web.png rename to docker-hub/images/login-web.png diff --git a/docs/images/merge_builds.png b/docker-hub/images/merge_builds.png similarity index 100% rename from docs/images/merge_builds.png rename to docker-hub/images/merge_builds.png diff --git a/docs/images/org-repo-collaborators.png b/docker-hub/images/org-repo-collaborators.png similarity index 100% rename from docs/images/org-repo-collaborators.png rename to docker-hub/images/org-repo-collaborators.png diff --git a/docs/images/orgs.png b/docker-hub/images/orgs.png similarity index 100% rename from docs/images/orgs.png rename to docker-hub/images/orgs.png diff --git a/docs/images/plus-carrot.png b/docker-hub/images/plus-carrot.png similarity index 100% rename from docs/images/plus-carrot.png rename to docker-hub/images/plus-carrot.png diff --git a/docs/images/prompt.png b/docker-hub/images/prompt.png similarity index 100% rename from docs/images/prompt.png rename to docker-hub/images/prompt.png diff --git a/docs/images/regex-help.png b/docker-hub/images/regex-help.png similarity index 100% rename from docs/images/regex-help.png rename to docker-hub/images/regex-help.png diff --git a/docs/images/register-web.png b/docker-hub/images/register-web.png similarity index 100% rename from docs/images/register-web.png rename to docker-hub/images/register-web.png diff --git a/docs/images/repo_links.png b/docker-hub/images/repo_links.png similarity index 100% rename from docs/images/repo_links.png rename to docker-hub/images/repo_links.png diff --git a/docs/images/repos.png b/docker-hub/images/repos.png similarity index 100% rename from docs/images/repos.png rename to docker-hub/images/repos.png diff --git a/docs/images/scan-drilldown.gif b/docker-hub/images/scan-drilldown.gif similarity index 100% rename from docs/images/scan-drilldown.gif rename to docker-hub/images/scan-drilldown.gif diff --git a/docs/images/scan-results.png b/docker-hub/images/scan-results.png similarity index 100% rename from docs/images/scan-results.png rename to docker-hub/images/scan-results.png diff --git a/docs/images/scan-tags.png b/docker-hub/images/scan-tags.png similarity index 100% rename from docs/images/scan-tags.png rename to docker-hub/images/scan-tags.png diff --git a/docs/index.md b/docker-hub/index.md similarity index 100% rename from docs/index.md rename to docker-hub/index.md diff --git a/docs/menu.md b/docker-hub/menu.md similarity index 100% rename from docs/menu.md rename to docker-hub/menu.md diff --git a/docs/official_repos.md b/docker-hub/official_repos.md similarity index 100% rename from docs/official_repos.md rename to docker-hub/official_repos.md diff --git a/docs/orgs.md b/docker-hub/orgs.md similarity index 100% rename from docs/orgs.md rename to docker-hub/orgs.md diff --git a/docs/repos.md b/docker-hub/repos.md similarity index 100% rename from docs/repos.md rename to docker-hub/repos.md diff --git a/docs/s3_website.json b/docker-hub/s3_website.json similarity index 100% rename from docs/s3_website.json rename to docker-hub/s3_website.json diff --git a/docs/webhooks.md b/docker-hub/webhooks.md similarity index 100% rename from docs/webhooks.md rename to docker-hub/webhooks.md diff --git a/dockerfiles/Dockerfile-node-alpine b/dockerfiles/Dockerfile-node-alpine deleted file mode 100644 index 5bfe426dc3..0000000000 --- a/dockerfiles/Dockerfile-node-alpine +++ /dev/null @@ -1,25 +0,0 @@ -FROM gliderlabs/alpine:3.2 - -ENV VERSION=v4.1.2 CMD=node DOMAIN=nodejs.org CFLAGS="-D__USE_MISC" -# ENV VERSION=v2.2.1 CMD=iojs DOMAIN=iojs.org NO_NPM_UPDATE=true - -# For base builds -ENV CONFIG_FLAGS="--without-npm" RM_DIRS=/usr/include -# ENV CONFIG_FLAGS="--fully-static --without-npm" DEL_PKGS="libgcc libstdc++" RM_DIRS=/usr/include - -RUN apk-install curl make gcc g++ python linux-headers paxctl libgcc libstdc++ && \ - curl -sSL https://${DOMAIN}/dist/${VERSION}/${CMD}-${VERSION}.tar.gz | tar -xz && \ - cd /${CMD}-${VERSION} && \ - ./configure --prefix=/usr ${CONFIG_FLAGS} && \ - make -j$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \ - make install && \ - paxctl -cm /usr/bin/${CMD} && \ - cd / && \ - if [ -x /usr/bin/npm -a -z "$NO_NPM_UPDATE" ]; then \ - npm install -g npm && \ - find /usr/lib/node_modules/npm -name test -o -name .bin -type d | xargs rm -rf; \ - fi && \ - apk del curl make gcc g++ python linux-headers paxctl ${DEL_PKGS} && \ - rm -rf /etc/ssl /${CMD}-${VERSION} ${RM_DIRS} \ - /usr/share/man /tmp/* /root/.npm /root/.node-gyp \ - /usr/lib/node_modules/npm/man /usr/lib/node_modules/npm/doc /usr/lib/node_modules/npm/html diff --git a/dockerfiles/Dockerfile-prod-build b/dockerfiles/Dockerfile-prod-build deleted file mode 100644 index a70cd28bd7..0000000000 --- a/dockerfiles/Dockerfile-prod-build +++ /dev/null @@ -1,22 +0,0 @@ -FROM bagel/universe:dc9b2190001e9c64d7b5e63dbf9999b2e4c83d25 - -ENV ENV production -ENV NODE_ENV production - -COPY ./app /opt/hub/app -COPY ./Makefile /opt/hub/Makefile -COPY ./_webpack /opt/hub/_webpack -COPY ./gulpfile.js /opt/hub/gulpfile.js -COPY ./gulp-tasks /opt/hub/gulp-tasks -COPY ./app-server /opt/hub/app-server -COPY ./.eslintrc /opt/hub/.eslintrc - -RUN make server-prod-target -RUN make server-extras -RUN make js-prod -RUN make images-prod -RUN make docker-font-prod -RUN gulp images::prod -RUN make styles-base-prod -RUN make stats-dir -RUN make css-stats diff --git a/dockerfiles/Dockerfile-stage-build b/dockerfiles/Dockerfile-stage-build deleted file mode 100644 index f6aeda2ebb..0000000000 --- a/dockerfiles/Dockerfile-stage-build +++ /dev/null @@ -1,22 +0,0 @@ -FROM bagel/universe:dc9b2190001e9c64d7b5e63dbf9999b2e4c83d25 - -ENV ENV staging -ENV NODE_ENV staging - -COPY ./app /opt/hub/app -COPY ./Makefile /opt/hub/Makefile -COPY ./_webpack /opt/hub/_webpack -COPY ./gulpfile.js /opt/hub/gulpfile.js -COPY ./gulp-tasks /opt/hub/gulp-tasks -COPY ./app-server /opt/hub/app-server -COPY ./.eslintrc /opt/hub/.eslintrc - -RUN make server-prod-target -RUN make server-extras -RUN make js-stage -RUN make images-prod -RUN make docker-font-prod -RUN gulp images::prod -RUN make styles-base-prod -RUN make stats-dir -RUN make css-stats diff --git a/dockerfiles/milky-way b/dockerfiles/milky-way deleted file mode 100644 index 2dc5b9c516..0000000000 --- a/dockerfiles/milky-way +++ /dev/null @@ -1,10 +0,0 @@ -FROM node:4.1.2 - -WORKDIR /opt/hub -ENV PATH /opt/hub/node_modules/.bin/:$PATH - -RUN apt-get update -COPY ./private-deps /opt/hub/private-deps -COPY ./package.json /opt/hub/ -ADD ./node_modules /opt/hub/node_modules -#RUN npm install --production diff --git a/dockerfiles/milky-way-no-bin b/dockerfiles/milky-way-no-bin deleted file mode 100644 index 79f1d8678c..0000000000 --- a/dockerfiles/milky-way-no-bin +++ /dev/null @@ -1,7 +0,0 @@ -FROM bagel/milky-way:dc9b2190001e9c64d7b5e63dbf9999b2e4c83d25 - -RUN rm -rf /opt/hub/node_modules/.bin && \ - ls && \ - tar -czf modules.tar ./node_modules/* - -CMD ["cat", "/opt/hub/modules.tar"] diff --git a/dockerfiles/saas-config b/dockerfiles/saas-config deleted file mode 100644 index e11d8a25de..0000000000 --- a/dockerfiles/saas-config +++ /dev/null @@ -1,29 +0,0 @@ -FROM bagel/universe:dc9b2190001e9c64d7b5e63dbf9999b2e4c83d25 - -# Source -COPY ./app /opt/hub/app -# Webpack -COPY ./webpack.config.js /opt/hub/webpack.config.js -COPY ./_webpack /opt/hub/_webpack -# Make -COPY ./Makefile /opt/hub/Makefile -# Gulp -COPY ./gulpfile.js /opt/hub/gulpfile.js -COPY ./gulp-tasks /opt/hub/gulp-tasks -# ESLint -COPY ./.eslintrc /opt/hub/.eslintrc -# Flow -ENV LOGNAME bagels -COPY ./flow-libs /opt/hub/flow-libs -COPY .flowconfig /opt/hub/.flowconfig -ENV PATH /opt/flow/:$PATH - -RUN npm install -RUN DEBUG=* ENV=local webpack -d -RUN make server-target -RUN make styles-base -RUN gulp images::dev -RUN make images -RUN make docker-font-dev -# favicon -COPY ./app/favicon.ico /opt/hub/app/.build/ diff --git a/dockerfiles/universe b/dockerfiles/universe deleted file mode 100644 index 432d53dc98..0000000000 --- a/dockerfiles/universe +++ /dev/null @@ -1,13 +0,0 @@ -FROM bagel/milky-way:dc9b2190001e9c64d7b5e63dbf9999b2e4c83d25 - -ENV NODE_ENV development - -RUN apt-get install libelf-dev unzip -y - -RUN cd /opt && wget http://flowtype.org/downloads/flow-linux64-latest.zip && unzip flow-linux64-latest.zip && rm flow-linux64-latest.zip - -# npm global deps -RUN npm install -g gulp jest-cli - -# npm deps -RUN cd /opt/hub && npm install diff --git a/fabfile.py b/fabfile.py deleted file mode 100644 index 80d2a1aedc..0000000000 --- a/fabfile.py +++ /dev/null @@ -1,14 +0,0 @@ -from fabric.api import run - -def start_project(email="none", user="none", auth="none", beta_password="maybejustnotsomeemptyspaceyea?", sha="latest", new_relic_key="", new_relic_app_name="hub-stage-node"): - run('docker rm $(docker ps -a -q) > /dev/null 2>&1 || :') - run('docker rmi $(docker images -q) > /dev/null 2>&1 || :') - run('cd /home/') - run('docker login -e %s -u %s -p %s' % (email, user, auth)) - run('docker pull bagel/hub-prod:%s' % sha) - run('docker pull bagel/haproxy_beta:latest') - run("docker ps | awk '{if($1 != \"CONTAINER\"){print $1}}' | xargs -r docker kill") - # We should tag the image with the git commit and deploy that instead of "latest" - run('docker run -dp 7001:3000 -e ENV=production --restart=on-failure:5 -e HUB_API_BASE_URL=https://hub-beta-stage.docker.com -e REGISTRY_API_BASE_URL=https://hub-beta-stage.docker.com -e NEW_RELIC_LICENSE_KEY=%s -e NEW_RELIC_APP_NAME=%s bagel/hub-prod:%s' % (new_relic_key, new_relic_app_name, sha)) - # HAProxy doesn't change a lot. We should check the image names before killing/rebooting - run('docker run -dp 80:80 -p 443:443 -e BETA_PASSWORD=%s --restart=on-failure:5 -v /opt/haproxy.pem:/haproxy/keys/hub-beta.docker.com/hub-beta.docker.pem bagel/haproxy_beta:latest' % beta_password) diff --git a/flow-libs/async.js b/flow-libs/async.js deleted file mode 100644 index 2d9f0cccef..0000000000 --- a/flow-libs/async.js +++ /dev/null @@ -1,12 +0,0 @@ -type AsyncCallback = (err: ?Object, results: ?any) => void; -type ParallelFuncs = (callback: AsyncCallback) => void; - -declare module 'async' { - declare function parallel(tasks: Array | Object, - callback: AsyncCallback): void - declare function series(tasks: Array, - callback: AsyncCallback): void - declare function each(arr: Array, - func: Function, - callback: Function): void -} \ No newline at end of file diff --git a/flow-libs/debug.js b/flow-libs/debug.js deleted file mode 100644 index 4807c40f8a..0000000000 --- a/flow-libs/debug.js +++ /dev/null @@ -1,5 +0,0 @@ -type DebugFunction = (thing: any) => void; - -declare module 'debug' { - declare function exports(string: string): DebugFunction; -} \ No newline at end of file diff --git a/flow-libs/fluxible.js b/flow-libs/fluxible.js deleted file mode 100644 index 3ad2f4e95f..0000000000 --- a/flow-libs/fluxible.js +++ /dev/null @@ -1,4 +0,0 @@ -export type FluxibleActionContext = { - dispatch(eventName: string, - payload: any): void; -} diff --git a/flow-libs/hub-js-sdk.js b/flow-libs/hub-js-sdk.js deleted file mode 100644 index 79da45ff99..0000000000 --- a/flow-libs/hub-js-sdk.js +++ /dev/null @@ -1,74 +0,0 @@ -type SuperAgentCallback = (err: any, - res: any) => void; - -type JWT = String; -type ChangePasswordData = { - username: String; - oldpassword: String; - newpassword: String -} - -declare module 'hub-js-sdk' { - declare var Auth: { - getToken(username: string, - password: string, - cb: SuperAgentCallback): void; - } - declare var Repositories: { - createRepository(jwt: JWT, - repository: any, - cb: SuperAgentCallback): void; - getReposForUser(jwt: JWT, - username: String, - cb: SuperAgentCallback): void - } - declare var Emails: { - getEmailSubscriptions(JWT: JWT, - user: String, - cb: SuperAgentCallback): void; - unsubscribeEmails(JWT: JWT, - user: String, - data: Object, - cb: SuperAgentCallback): void; - subscribeEmails(JWT:JWT, - user: String, - data: Object, - cb: SuperAgentCallback): void; - getEmailsJWT(JWT:JWT, - cb:SuperAgentCallback): void; - getEmailsForUser(JWT: JWT, - user: String, - cb: SuperAgentCallback): void; - deleteEmailByID(JWT: JWT, - id: String, - cb: SuperAgentCallback): void; - updateEmailByID(JWT: JWT, - id: String, - data: Object, - cb: SuperAgentCallback): void; - addEmailsForUser(JWT: JWT, - user: Object, - email: string, - cb: SuperAgentCallback): void; - } -} - -declare module 'hub-js-sdk/src/Hub/SDK/Users' { - declare function changePassword(JWT: JWT, - data: ChangePasswordData, - cb: SuperAgentCallback): void; - declare function getUser(JWT: JWT, - user: String, - cb: SuperAgentCallback): void; -} - -declare module 'hub-js-sdk/src/Hub/SDK/Auth' { - declare function getToken(username: String, - password: String, - cb: SuperAgentCallback): void; -} - -declare module 'hub-js-sdk/src/Hub/SDK/Notifications' { - declare function getActivityFeed(JWT: JWT, - cb: SuperAgentCallback): void; -} diff --git a/flow-libs/lodash.js b/flow-libs/lodash.js deleted file mode 100644 index a047b9e1b5..0000000000 --- a/flow-libs/lodash.js +++ /dev/null @@ -1,5 +0,0 @@ -declare module 'lodash' { - declare function sortByOrder(arr: Array, - properties: Array, - sortOrder: Array): Array; -} \ No newline at end of file diff --git a/gulp-tasks/img.js b/gulp-tasks/img.js deleted file mode 100644 index 524d9a86f6..0000000000 --- a/gulp-tasks/img.js +++ /dev/null @@ -1,24 +0,0 @@ -var gulp = require('gulp'); -var imagemin = require('gulp-imagemin'); -var pngquant = require('imagemin-pngquant'); - -//Hub2 Images for dev & production (There is a separate task for docker-ux images) -gulp.task('images::dev', function () { - return gulp.src('app/img/**') - .pipe(imagemin({ - progressive: true, - svgoPlugins: [{removeViewBox: false}], - use: [pngquant({ quality: '65-80', speed: 4 })] - })) - .pipe(gulp.dest('app/.build/public/img')); -}); - -gulp.task('images::prod', function() { - return gulp.src('app/img/**') - .pipe(imagemin({ - progressive: true, - svgoPlugins: [{removeViewBox: false}], - use: [pngquant({ quality: '65-80', speed: 4 })] - })) - .pipe(gulp.dest('.tmp/server/build/img')); -}); diff --git a/gulpfile.js b/gulpfile.js deleted file mode 100644 index 05734a32b9..0000000000 --- a/gulpfile.js +++ /dev/null @@ -1,3 +0,0 @@ -'use strict'; -require('./gulp-tasks/img'); - diff --git a/local.Dockerfile b/local.Dockerfile deleted file mode 100644 index 794df7bc63..0000000000 --- a/local.Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -FROM bagel/universe:dc9b2190001e9c64d7b5e63dbf9999b2e4c83d25 - -ENV ENV local -ENV NODE_ENV local - -COPY ./app /opt/hub/app -COPY ./Makefile /opt/hub/Makefile -COPY ./_webpack /opt/hub/_webpack -COPY ./gulpfile.js /opt/hub/gulpfile.js -COPY ./gulp-tasks /opt/hub/gulp-tasks -COPY ./app-server /opt/hub/app-server -COPY ./.eslintrc /opt/hub/.eslintrc - -RUN make server-prod-target -RUN make server-extras -RUN make js-local -RUN make images-prod -RUN make docker-font-prod -RUN gulp images::prod -RUN make styles-base-prod -RUN make stats-dir -RUN make css-stats diff --git a/package.json b/package.json deleted file mode 100644 index f73588bdf2..0000000000 --- a/package.json +++ /dev/null @@ -1,113 +0,0 @@ -{ - "name": "docker-2.0", - "version": "0.0.1", - "private": true, - "scripts": { - "test": "jest", - "build:dev": "DEBUG=* webpack -dw" - }, - "jest": { - "rootDir": "./app/scripts", - "scriptPreprocessor": "../../node_modules/babel-jest", - "testFileExtensions": [ - "js" - ], - "moduleFileExtensions": [ - "jsx", - "js", - "json" - ], - "modulePathIgnorePatterns": [ - "/node_modules/" - ], - "unmockedModulePathPatterns": [ - "react" - ] - }, - "dependencies": { - "@dux/element-button": "0.0.3", - "@dux/element-card": "0.0.7", - "@dux/element-markdown": "0.0.8", - "@dux/hub-sdk": "^0.1.1", - "async": "^1.3.0", - "babel": "^5.6.14", - "babel-core": "^5.6.14", - "babel-runtime": "^5.6.18", - "body-parser": "^1.12.2", - "bugsnag": "^1.7.0", - "classnames": "^2.1.2", - "cookie": "^0.2.3", - "cookie-parser": "^1.3.4", - "csurf": "^1.8.0", - "debug": "^2.1.3", - "dux": "file:./private-deps/docker-ux", - "express": "^4.12.3", - "express-state": "^1.2.0", - "fluxible": "^1.0.3", - "fluxible-addons-react": "^0.2.0", - "highlight.js": "^9.0.0", - "history": "^1.17.0", - "hub-js-sdk": "file:./private-deps/hub-js-sdk", - "immutable": "^3.7.6", - "keymirror": "^0.1.1", - "lodash": "^3.6.0", - "marked": "^0.3.3", - "md5": "^2.0.0", - "moment": "^2.10.3", - "newrelic": "christopherbiscardi/node-newrelic#c4ccca3764acafaf9c5899e4a1abece828e1f7b8", - "normalizr": "^1.4.0", - "numeral": "^1.5.3", - "rc-tooltip": "^3.3.0", - "react": "^0.14.7", - "react-dom": "^0.14.3", - "react-router": "^1.0.0", - "react-select": "^1.0.0-beta6", - "recurly-js": "git://github.com/recurly/recurly-js#d9740eb3ee416fb999635daecfb524a492dbb058", - "redux": "^3.0.5", - "redux-logger": "^2.3.2", - "redux-ui": "0.0.8", - "remarkable": "^1.6.0", - "reselect": "^2.0.1", - "serialize-javascript": "^1.0.0", - "serve-favicon": "^2.2.0", - "superagent": "^1.1.0", - "svg-inline-react": "^0.3.1", - "velocity-animate": "^1.2.3", - "velocity-react": "1.1.3" - }, - "devDependencies": { - "babel-eslint": "^4.0.0", - "babel-jest": "^5.0.1", - "babel-loader": "^5.0.0", - "css-loader": "^0.23.0", - "cssnano": "^3.2.0", - "cssstats": "^1.10.0", - "eslint": "^1.2.1", - "eslint-loader": "^1.0.0", - "extract-text-webpack-plugin": "^0.9.1", - "gulp": "^3.8.11", - "gulp-imagemin": "^2.2.1", - "imagemin-pngquant": "^4.0.0", - "json-loader": "^0.5.2", - "lost": "^6.6.2", - "nodemon": "^1.3.7", - "postcss-browser-reporter": "^0.4.0", - "postcss-constants": "^0.1.1", - "postcss-cssnext": "^2.1.0", - "postcss-cssstats": "^1.0.0", - "postcss-each": "^0.7.0", - "postcss-import": "^7.0.0", - "postcss-loader": "^0.8.0", - "postcss-nested": "^1.0.0", - "postcss-url": "^5.0.1", - "react-redux": "^4.0.3", - "redux": "^3.0.5", - "reselect": "^2.0.1", - "style-loader": "^0.13.0", - "svg-inline-loader": "^0.4.0", - "webpack": "^1.10" - }, - "engines": { - "node": ">=4.0.0" - } -} diff --git a/pr-docs/css.md b/pr-docs/css.md deleted file mode 100644 index f019c08e6c..0000000000 --- a/pr-docs/css.md +++ /dev/null @@ -1,62 +0,0 @@ -[Demo](https://css-modules.github.io/webpack-demo/) - -The approach is thus: Use Foundation as a "browser reset" stylesheet, -then put everything that isn't a foundation `_settings.scss` variable -in CSSModule sidecar files. This links our javascript modules with our -css and increases the ease with which we can create a module library. - -# Implementation - -## File Structure - -``` -app/scripts/ -|-- ScopedSelectors.js -|-- ScopedSelectors.css -``` - -## Usage - -```javascript -import styles from './ScopedSelectors.css'; - -import React, { Component } from 'react'; - -export default class ScopedSelectors extends Component { - - render() { - return ( -
    -

    Scoped Selectors

    -
    - ); - } - -}; -``` - -```css -.root { - border-width: 2px; - border-style: solid; - border-color: #777; - padding: 0 20px; - margin: 0 6px; - max-width: 400px; -} - -.text { - color: #777; - font-size: 24px; - font-family: helvetica, arial, sans-serif; - font-weight: 600; -} -``` - -# Approach - -* modules should be scoped to themselves and not affect children or - siblings. -* Webpack already has support for css-modules in it's `css-loader`. So - we'll start with that. -* [css-modules and preprocessors (sass)](https://github.com/css-modules/css-modules#usage-with-preprocessors) diff --git a/pr-docs/linting.md b/pr-docs/linting.md deleted file mode 100644 index e66ad8c472..0000000000 --- a/pr-docs/linting.md +++ /dev/null @@ -1,28 +0,0 @@ -# Linting - -All code must pass [ESLint][eslint] before being merged into master -branch. The ESLint config can be found in `.eslintrc` and is -integrated into webpack. - -# Running ESLint - -``` -gulp webpack -``` - -Since linting is integrated with webpack, it is possible to lint code -while it is being developed without any extra effort. This is -important because if it is not approximate to effortless to run -linting, it will not be run while developing. - -# We should block deploys for linting errors - -Since we do CI/CD, the static analysis present in ESLint can help us -catch bugs before shipping. We should therefore block deploys if -ESLint detects an error-level (level `2` in `.eslintrc`) issue. - -* [eslint][eslint] -* [babel-eslint][babel-eslint] - -[eslint]: http://eslint.org/ -[babel-eslint]: https://github.com/babel/babel-eslint diff --git a/pr-docs/routes.md b/pr-docs/routes.md deleted file mode 100644 index 99876f2e52..0000000000 --- a/pr-docs/routes.md +++ /dev/null @@ -1,262 +0,0 @@ -# Routes - -Two items affect this proposal. - -1. [Distribution's work](https://github.com/docker/distribution), - specifically relating to defining Repositories, Images, Manifests, - Digests and Tags. -2. The Current Hub's Routing Issues - -## Distributions Work (partially summarized) - -### Repository - -* A set of blobs -* Subsets of these blobs make up Images - -### Image - -* A set of blobs - - Layers - - Tag - - Signatures - - Manifest -* A Tag (potentially containing signatures) points to a Manifest -* A Manifest points to multiple layers. - -### Manifest - -As defined in the [distribution][manifest-pr] Manifest PR: - -> A [Content Manifest][manifest] is a simple JSON file which contains -> general fields that are typical to any package management -> system. The goal is for these manifests to describe an application -> and its dependencies in a content-addressable and verifiable way. - -### Tag - -As defined in the [distribution][d-tag-pr] PR: - -> A [tag][tag] is simply a named pointer to content. The content can -> be any blob but should mostly be a manifest. One can sign tags to -> later verify that they were created by a trusted party. - -### Additional Content - -Image names will be allowed to have many slashes in the future. - -## Current Hub Issues - -### Collisions - -The URLs for user and repo collide: - -A user's Starred Repos: - -``` -/u/biscarch/starred/ -``` - -A user's repository, named Starred. - -``` -/u/biscarch/starred/ -``` - -## Future Problems - -An image for the user `biscarch`, named `my/repo`: - -``` -/u/biscarch/my/repo/ -``` - -An image for the user `biscarch`, named `my`, tagged `repo`: - -``` -/u/biscarch/my/repo/ -``` - -## Solutions - -Namespace `Users`, `Repos` and `Images` as such (with the user -`biscarch`) - -``` -/u/:user -/r/:user/:repo -/i/:user/:repo/:tag -``` - -### Solving Starred Repos - -Prefix defines whether we are referring to a repo or attribute of a -user: - -``` -/u/biscarch/starred -/r/biscarch/starred -``` - -### Solving Repo/Image Conflicts - -Prefix determines whether we are referring to a Repository or Image: - -``` -/r/biscarch/my/repo/ -/i/biscarch/my/repo/ -``` - -## The new Spec - -``` -/u/ -/u/:user/ -/r/:user/:repo/ -/i/:user/:repo/:tag/ -``` - -### Full List - -### Dashboard - -`/` - -### Official Repositories - -"username" === library, which is represented as the root `_`. -All management of `library` namespaced repos is done from the usual -`/u/library/:repo/` - -``` -/_/:repo/ -/_/:repo/dockerfile/ -/_/:repo/dockerfile/raw -/_/:repo/tags/ -``` - -### Single Endpoints - -* Search - - `/search/` -* Plans - - `/plans/` - -### Account - -Mostly Settings; Add Repository Page; - -`/account/` should redirect to `/account/settings/` - -``` -/account/accounts/ -/account/authorized_services/ -/account/change-password/ -/account/confirm-email// -/account/emails/ -/account/notifications/ -/account/organizations/ -/account/organizations/:org_name/ -/account/organizations/:org_name/groups/:group_id/ -/account/repositories/add/ -/account/settings/ -/account/subscriptions/ -``` - -### Users - -``` -/u/ -/u/:user/ -/u/:user/activity/ -/u/:user/contributed/ -/u/:user/starred/ -``` - -### Repos - -``` -/r/:user/:repo/ -/r/:user/:repo/~/settings/ -/r/:user/:repo/~/settings/collaborators/ -/r/:user/:repo/~/settings/links/ -/r/:user/:repo/~/settings/triggers/ -/r/:user/:repo/~/settings/webhooks/ -/r/:user/:repo/~/settings/tags/ -``` - -Current build history urls: - -``` -/r/:user/:repo/~/builds_history/ -``` - -### Images - -We currently don't do a lot for Images. Repositories have been the -main focus. - -``` -/i/:user/:repo/:tag/ -/i/:user/:repo/:tag/~/dockerfile/ -/i/:user/:repo/:tag/~/dockerfile/raw/ -``` - -### Automated Builds - -``` -/automated-builds/ -/builds/ -/builds/:user/:repo/ -``` - -### Convenience Redirects - -Also, potential pages to build out more agressively. - -* `/official/` - - redirects to `/search?q=library&f=official` - - future: Potentially `Explore` type page for official repos -* `/most_stars/`, `/popular/` - - redirects to `search?q=library&s=stars` -* `/recent_updated/` - - `search?q=library&s=last_updated` - -#### Help - -* `/help` - - `https://www.docker.com/resources/help/` - - Can we rely on this url to stick around? -* `/help/docs` - - `https://docs.docker.com/` - -## Make Separate Sites for: - -### Highland URLs - -We need to pull out the APIs used on the current Hub for this. - -``` -/highland/ -/highland/build-configs/ -/highland/builds/ -/highland/search/ -/highland/stats/ -``` - - -## More Issues - -* There are no links to comments -* `/opensearch.xml` times out on the current site - - Should we re-implement? -* `/sitemap.xml` - -# Concerns with this Proposal - -* Automated Build urls need to be given more thought - -[tag]: https://github.com/stevvooe/distribution/blob/a8d3f3474b7b60576dc64250d95db3717bf07c33/doc/spec/tags.md#tags -[d-tag-pr]: https://github.com/docker/distribution/pull/173/files -[d-manifest-pr]: https://github.com/docker/distribution/pull/62 -[manifest]: https://github.com/jlhawn/distribution/blob/e8b5c8c32b565b9b643c3a0b0e87339bf40eb206/doc/spec/manifest.md diff --git a/production_ready.md b/production_ready.md deleted file mode 100644 index ee92e5a3b3..0000000000 --- a/production_ready.md +++ /dev/null @@ -1,93 +0,0 @@ -Production Readiness: Docker Hub Front-End (hub-web-v2) -================================ - -Testing -------- - - * **What is the max traffic load that your service has been tested with?** - Hub UI has not been load tested. - - * **How has the service been soak-tested?** - Hub UI has not been soak tested. - - Monitoring - ---------- - - * **How do you monitor?** - New Relic for server monitoring, BugSnag for JavaScript errors and PagerDuty for alerting. - - * **What’s the link(s) to the dashboard(s)?** - New Relic: https://rpm.newrelic.com/accounts/532547/applications/8853774 - BugSnag: https://bugsnag.com/docker/hub-prod/errors - PagerDuty: https://docker.pagerduty.com/services/PKZG21B - - * **Do you use an exception tracking service (e.g. Bugsnag, Sentry, New Relic)?** - Yes, BugSnag and New Relic. - - * **What’s the health check endpoint? And what checks does that endpoint perform?** - https://hub.docker.com/_health/ - - * **What external services do you depend on? How do you monitor them and handle failures?** - Hub API Gateway and all downstream Docker Cloud services. - Google Tag Manager (gtm.js) - Recurly (recurly.js) - - - - * **What’s the link to view the logs?** - - Alerting - -------- - - * **How do you know if your service is down?** - PagerDuty alerts - Prometheus alerts - - * **What are the metrics that you alert on?** - 500's from Front End containers - - * **Have you tested tripping on an alert to page somebody?** - Not manually tested. But production systems are paging properly. - - * **What’s the link to your on-call schedule?** - https://docker.pagerduty.com/schedules#P88XAI9 - - * **Where is your on-call run-book?** - https://docker.atlassian.net/wiki/display/DE/Hub+UI+Runbook - - Disaster - -------- - - * **What’s the plan if your persistence layer blows up?** - Front-end is stateless so this shouldn't be required, but restart Container if unsure. - - * **What’s the plan if any of your external service dependencies blows up?** - Hub API Gateway or downstream service - find service owner, escalate/alert through PagerDuty, contact service team via Slack. - Google Tag Manager - disable Google Tag Manager from https://tagmanager.google.com - single signon with docker.com account - Recurly problem - check status.recurly.com, escalate/alert Billing team through PagerDuty, contact service team via Slack. - Update status.io describing impact to UI if any. - - - Security - -------- - - * **Is the service exposed on the public internet? Does it require TLS?** - https://hub.docker.com/ - - * **How do you store production secrets?** - Front-End does not store secrets. JWT is stored in user's browser cookie. - - * **What is your authentication model (both user authentication and service-to-service authentication)?** - oauth - - * **Do you store any sensitive user data (emails, phone numbers, intellectual property)?** - JWT in cookie. - - Release process - --------------- - - * **What’s the link to your docs on how to do a release?** - https://docker.atlassian.net/wiki/display/DH/Hub+frontend+Deployment+Process - - * **How long does it take to release a code fix to production?** - 4-8 hours diff --git a/startup-scripts/boot-dev-tmux.sh b/startup-scripts/boot-dev-tmux.sh deleted file mode 100755 index 0907330ac3..0000000000 --- a/startup-scripts/boot-dev-tmux.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash - -set -e - -eval $(docker-machine env dev) - -############################################################### -# You must have `tmux` installed locally. On OSX, this can be # -# accomplished with `brew install tmux` # -############################################################### - -SESSION=HubDev -DIR=${PWD##*/}_hub_1 -CONTAINER=$(sed s/-//g <<< $DIR) - - -# Create new tmux session -tmux -2 new-session -d -s $SESSION - -# Window 1 - -## webpack task -tmux split-window -tmux select-pane -t 0 -tmux send-keys "DEBUG=* webpack -wd" C-m - -## styles - -tmux select-pane -t 1 -tmux send-keys "DEBUG=* gulp watch::styles::dev" C-m - -## Flow - -tmux split-window -h -tmux select-pane -t 2 -tmux send-keys "flow" C-m - -## docker logs - -tmux select-pane -t 0 -tmux split-window -h -tmux send-keys "docker-compose logs hub" C-m - -# Attach to session -tmux -2 attach-session -t $SESSION diff --git a/startup-scripts/boot-dev.sh b/startup-scripts/boot-dev.sh deleted file mode 100755 index 83b569ffe3..0000000000 --- a/startup-scripts/boot-dev.sh +++ /dev/null @@ -1,2 +0,0 @@ -DEBUG=* webpack -dw & -cd app/.build && nodemon ./server.js diff --git a/startup-scripts/bootstrap-dev.sh b/startup-scripts/bootstrap-dev.sh deleted file mode 100755 index 454c4620fa..0000000000 --- a/startup-scripts/bootstrap-dev.sh +++ /dev/null @@ -1,8 +0,0 @@ -# run this before the development container to bootstrap your local filesystem -npm install -cp app/favicon.ico app/.build/favicon.ico -make server-target -make styles-base -gulp images::dev -make images -make docker-font-dev diff --git a/webpack.config.js b/webpack.config.js deleted file mode 100644 index 9a5242e5ec..0000000000 --- a/webpack.config.js +++ /dev/null @@ -1,151 +0,0 @@ -const debug = require('debug')('webpack-debug'); -var ENV_CONFIG = require('./_webpack/_envConfig.js'); -var fs = require('fs'); -var path = require('path'); -var ExtractTextPlugin = require("extract-text-webpack-plugin"); -var _ = require('lodash'); -var webpack = require('webpack'); - -var loaders = require('./_webpack/_commonLoaders'); - -/** - * blacklist this array from being included in `externals`. - * - * This has the effect of making any modules in this list be - * resolved at build time instead of runtime. This affects the - * server bundle - */ -var blacklist = ['.bin', 'hub-js-sdk', 'dux']; -var node_modules = fs.readdirSync('node_modules').filter(function(x) { - return !_.includes(blacklist, x); -}); - -/* Dux Button Config */ -var elementButton = require('@dux/element-button/defaults'); -var buttons = elementButton.mkButtons([{ - name: 'primary', - color: '#FFF', - bg: '#22B8EB' -},{ - name: 'secondary', - color: '#FFF', - bg: '#232C37' -},{ - name: 'coral', - color: '#FFF', - bg: '#FF85AF' -},{ - name: 'success', - color: '#FFF', - bg: '#0FD85A' -},{ - name: 'warning', - color: '#FFF', - bg: '#FF8546' -},{ - name: 'yellow', - color: '#FFF', - bg: '#FFDE50' -},{ - name: 'alert', - color: '#FFF', - bg: '#EB3E46' -}]); -debug('modules that will be runtime require dependencies of the server if the server requires them: ', node_modules); -var commonConfig = { - resolve: { - extensions: ['', '.js', '.jsx', '.json'], - root: [ - path.resolve(__dirname, './app/scripts/'), - path.resolve(__dirname, './app/scripts/components/') - ], - modulesDirectories: ['node_modules', 'app/scripts'] - }, - module: { - preLoaders: loaders.preLoaders, - loaders: loaders.commonLoaders - }, - plugins: [ - ENV_CONFIG, - new webpack.optimize.DedupePlugin(), - new ExtractTextPlugin('public/styles/style.css', { allChunks: true }) - ], - postcss: [ - require('postcss-import')(), - require('postcss-constants')({ - defaults: _.merge(require('@dux/element-card/defaults')({ - capBackground: '#f1f6fb', - borderColor: '#c4cdda' - }), - { - duxElementButton: { - radius: '.25rem', - buttons: buttons - } - }) - }), - require('postcss-each'), - require('postcss-cssnext')({ - browsers: 'last 2 versions', - features: { - // https://github.com/robwierzbowski/node-pixrem/issues/40 - rem: false - } - }), - require('postcss-nested'), - require('lost')({ - gutter: '1.25rem', - flexbox: 'flex' - }), - require('postcss-cssstats')(function(stats) { - /** - * this is in test-phase because it runs on all - * files individually. We should either figure out - * that that is useful or get it to run on the full postcss - * AST or extracted CSS file. - */ - debug(stats); - }), - require('postcss-url')(), - require('cssnano')(), - require('postcss-browser-reporter') - ], - eslint: { - failOnError: true - }, - profile: true -} - -var clientBundle = _.assign({}, - commonConfig, - { - // client.js - entry: './app/scripts/client.js', - devtool: 'eval-source-map', - output: { - path: 'app/.build/public/', - filename: 'js/client.js' - } - }); - -var serverBundle = _.assign({}, - commonConfig, - { - // server.js - entry: './app/scripts/server.js', - output: { - path: 'app/.build/', - filename: 'server.js', - libraryTarget: 'commonjs2' - }, - target: 'node', - externals: node_modules, - node: { - __dirname: '/opt/hub/' - } - }); - -module.exports = [ - clientBundle, - serverBundle -];