diff --git a/.eslintrc.js b/.eslintrc.js index 2eb86f64..3c6c4baf 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -16,9 +16,7 @@ module.exports = { ], globals: { "NODE_ENV": false, - "VERSION": false, - "GOOGLE_CLIENT_ID": false, - "GITHUB_CLIENT_ID": false + "VERSION": false }, // check if imports actually resolve 'settings': { diff --git a/build/webpack.dev.conf.js b/build/webpack.dev.conf.js index fbebcecd..6ec2eef5 100644 --- a/build/webpack.dev.conf.js +++ b/build/webpack.dev.conf.js @@ -19,9 +19,7 @@ module.exports = merge(baseWebpackConfig, { devtool: 'source-map', plugins: [ new webpack.DefinePlugin({ - NODE_ENV: config.dev.env.NODE_ENV, - GOOGLE_CLIENT_ID: config.dev.env.GOOGLE_CLIENT_ID, - GITHUB_CLIENT_ID: config.dev.env.GITHUB_CLIENT_ID + NODE_ENV: config.dev.env.NODE_ENV }), // https://github.com/glenjamin/webpack-hot-middleware#installation--usage new webpack.HotModuleReplacementPlugin(), diff --git a/config/dev.env.js b/config/dev.env.js index 6b882aa6..efead7c8 100644 --- a/config/dev.env.js +++ b/config/dev.env.js @@ -2,7 +2,5 @@ var merge = require('webpack-merge') var prodEnv = require('./prod.env') module.exports = merge(prodEnv, { - NODE_ENV: '"development"', - GOOGLE_CLIENT_ID: '"241271498917-c3loeet001r90q6u79q484bsh5clg4fr.apps.googleusercontent.com"', - GITHUB_CLIENT_ID: '"cbf0cf25cfd026be23e1"' + NODE_ENV: '"development"' }) diff --git a/config/index.js b/config/index.js index b5211e47..9fecd843 100644 --- a/config/index.js +++ b/config/index.js @@ -24,7 +24,7 @@ module.exports = { dev: { env: require('./dev.env'), port: 8080, - autoOpenBrowser: true, + autoOpenBrowser: false, assetsSubDirectory: 'static', assetsPublicPath: '/', proxyTable: {}, diff --git a/config/prod.env.js b/config/prod.env.js index ee5d146f..773d263d 100644 --- a/config/prod.env.js +++ b/config/prod.env.js @@ -1,5 +1,3 @@ module.exports = { - NODE_ENV: '"production"', - GOOGLE_CLIENT_ID: '"241271498917-t4t7d07qis7oc0ahaskbif3ft6tk63cd.apps.googleusercontent.com"', - GITHUB_CLIENT_ID: '"30c1491057c9ad4dbd56"' + NODE_ENV: '"production"' } diff --git a/server/conf.js b/server/conf.js new file mode 100644 index 00000000..0394803f --- /dev/null +++ b/server/conf.js @@ -0,0 +1,37 @@ +const pandocPath = process.env.PANDOC_PATH || 'pandoc'; +const wkhtmltopdfPath = process.env.WKHTMLTOPDF_PATH || 'wkhtmltopdf'; +const userBucketName = process.env.USER_BUCKET_NAME || 'stackedit-users'; +const paypalUri = process.env.PAYPAL_URI || 'https://www.paypal.com/cgi-bin/webscr'; +const paypalReceiverEmail = process.env.PAYPAL_RECEIVER_EMAIL; + +const dropboxAppKey = process.env.DROPBOX_APP_KEY; +const dropboxAppKeyFull = process.env.DROPBOX_APP_KEY_FULL; +const githubClientId = process.env.GITHUB_CLIENT_ID; +const githubClientSecret = process.env.GITHUB_CLIENT_SECRET; +const googleClientId = process.env.GOOGLE_CLIENT_ID; +const googleApiKey = process.env.GOOGLE_API_KEY; +const wordpressClientId = process.env.WORDPRESS_CLIENT_ID; + +exports.values = { + pandocPath, + wkhtmltopdfPath, + userBucketName, + paypalUri, + paypalReceiverEmail, + dropboxAppKey, + dropboxAppKeyFull, + githubClientId, + githubClientSecret, + googleClientId, + googleApiKey, + wordpressClientId, +}; + +exports.publicValues = { + dropboxAppKey, + dropboxAppKeyFull, + githubClientId, + googleClientId, + googleApiKey, + wordpressClientId, +}; diff --git a/server/github.js b/server/github.js index eadb340c..83aff9e3 100644 --- a/server/github.js +++ b/server/github.js @@ -1,5 +1,6 @@ const qs = require('qs'); // eslint-disable-line import/no-extraneous-dependencies const request = require('request'); +const conf = require('./conf'); function githubToken(clientId, code) { return new Promise((resolve, reject) => { @@ -8,7 +9,7 @@ function githubToken(clientId, code) { url: 'https://github.com/login/oauth/access_token', qs: { client_id: clientId, - client_secret: process.env.GITHUB_SECRET, + client_secret: conf.values.githubClientSecret, code, }, }, (err, res, body) => { diff --git a/server/index.js b/server/index.js index 289d8519..0f116eee 100644 --- a/server/index.js +++ b/server/index.js @@ -6,6 +6,7 @@ const user = require('./user'); const github = require('./github'); const pdf = require('./pdf'); const pandoc = require('./pandoc'); +const conf = require('./conf'); const resolvePath = pathToResolve => path.join(__dirname, '..', pathToResolve); @@ -24,6 +25,7 @@ module.exports = (app, serveV4) => { } app.get('/oauth2/githubToken', github.githubToken); + app.get('/conf', (req, res) => res.send(conf.publicValues)); app.get('/userInfo', user.userInfo); app.post('/pdfExport', pdf.generate); app.post('/pandocExport', pandoc.generate); diff --git a/server/pandoc.js b/server/pandoc.js index 79b1505f..8ac0f3d3 100644 --- a/server/pandoc.js +++ b/server/pandoc.js @@ -3,6 +3,7 @@ const { spawn } = require('child_process'); const fs = require('fs'); const tmp = require('tmp'); const user = require('./user'); +const conf = require('./conf'); const outputFormats = { asciidoc: 'text/plain', @@ -90,10 +91,9 @@ exports.generate = (req, res) => { reject(error); } - const binPath = process.env.PANDOC_PATH || 'pandoc'; const format = outputFormat === 'pdf' ? 'latex' : outputFormat; params.push('-f', 'json', '-t', format, '-o', filePath); - const pandoc = spawn(binPath, params, { + const pandoc = spawn(conf.values.pandocPath, params, { stdio: [ 'pipe', 'ignore', diff --git a/server/pdf.js b/server/pdf.js index 7b849732..0fe4337a 100644 --- a/server/pdf.js +++ b/server/pdf.js @@ -3,6 +3,7 @@ const { spawn } = require('child_process'); const fs = require('fs'); const tmp = require('tmp'); const user = require('./user'); +const conf = require('./conf'); /* eslint-disable no-var, prefer-arrow-callback, func-names */ function waitForJavaScript() { @@ -127,10 +128,9 @@ exports.generate = (req, res) => { params.push('--page-size', !authorizedPageSizes.includes(options.pageSize) ? 'A4' : options.pageSize); // Use a temp file as wkhtmltopdf can't access /dev/stdout on Amazon EC2 for some reason - const binPath = process.env.WKHTMLTOPDF_PATH || 'wkhtmltopdf'; params.push('--run-script', `${waitForJavaScript.toString()}waitForJavaScript()`); params.push('--window-status', 'done'); - const wkhtmltopdf = spawn(binPath, params.concat('-', filePath), { + const wkhtmltopdf = spawn(conf.values.wkhtmltopdfPath, params.concat('-', filePath), { stdio: [ 'pipe', 'ignore', diff --git a/server/user.js b/server/user.js index 9ff126d7..6f94411e 100644 --- a/server/user.js +++ b/server/user.js @@ -1,13 +1,8 @@ const request = require('request'); const AWS = require('aws-sdk'); const verifier = require('google-id-token-verifier'); +const conf = require('./conf'); -const { - USER_BUCKET_NAME = 'stackedit-users', - PAYPAL_URI = 'https://www.paypal.com/cgi-bin/webscr', - PAYPAL_RECEIVER_EMAIL = 'stackedit.project@gmail.com', - GOOGLE_CLIENT_ID, -} = process.env; const s3Client = new AWS.S3(); const cb = (resolve, reject) => (err, res) => { @@ -20,7 +15,7 @@ const cb = (resolve, reject) => (err, res) => { exports.getUser = id => new Promise((resolve, reject) => { s3Client.getObject({ - Bucket: USER_BUCKET_NAME, + Bucket: conf.values.userBucketName, Key: id, }, cb(resolve, reject)); }) @@ -35,7 +30,7 @@ exports.getUser = id => new Promise((resolve, reject) => { exports.putUser = (id, user) => new Promise((resolve, reject) => { s3Client.putObject({ - Bucket: USER_BUCKET_NAME, + Bucket: conf.values.userBucketName, Key: id, Body: JSON.stringify(user), }, cb(resolve, reject)); @@ -43,13 +38,13 @@ exports.putUser = (id, user) => new Promise((resolve, reject) => { exports.removeUser = id => new Promise((resolve, reject) => { s3Client.deleteObject({ - Bucket: USER_BUCKET_NAME, + Bucket: conf.values.userBucketName, Key: id, }, cb(resolve, reject)); }); exports.getUserFromToken = idToken => new Promise((resolve, reject) => verifier - .verify(idToken, GOOGLE_CLIENT_ID, cb(resolve, reject))) + .verify(idToken, conf.values.googleClientId, cb(resolve, reject))) .then(tokenInfo => exports.getUser(tokenInfo.sub)); exports.userInfo = (req, res) => exports.getUserFromToken(req.query.idToken) @@ -78,7 +73,7 @@ exports.paypalIpn = (req, res, next) => Promise.resolve() sponsorUntil = Date.now() + (5 * 366 * 24 * 60 * 60 * 1000); // 5 years } if ( - req.body.receiver_email !== PAYPAL_RECEIVER_EMAIL || + req.body.receiver_email !== conf.values.paypalReceiverEmail || req.body.payment_status !== 'Completed' || req.body.mc_currency !== 'USD' || (req.body.txn_type !== 'web_accept' && req.body.txn_type !== 'subscr_payment') || @@ -90,7 +85,7 @@ exports.paypalIpn = (req, res, next) => Promise.resolve() // Processing PayPal IPN req.body.cmd = '_notify-validate'; return new Promise((resolve, reject) => request.post({ - uri: PAYPAL_URI, + uri: conf.values.paypalUri, form: req.body, }, (err, response, body) => { if (err) { diff --git a/src/components/ExplorerNode.vue b/src/components/ExplorerNode.vue index 092979f1..e3771a3f 100644 --- a/src/components/ExplorerNode.vue +++ b/src/components/ExplorerNode.vue @@ -156,7 +156,7 @@ export default { ...sourceNode.item, parentId: targetNode.item.id, }); - badgeSvc.addBadge('moveFiles'); + badgeSvc.addBadge(sourceNode.isFolder ? 'moveFolder' : 'moveFile'); } }, async onContextMenu(evt) { diff --git a/src/components/Notification.vue b/src/components/Notification.vue index 2ed2ac4c..d60a5ce6 100644 --- a/src/components/Notification.vue +++ b/src/components/Notification.vue @@ -3,7 +3,7 @@
- +
diff --git a/src/components/SideBar.vue b/src/components/SideBar.vue index 99819cb2..bf4019f9 100644 --- a/src/components/SideBar.vue +++ b/src/components/SideBar.vue @@ -175,8 +175,9 @@ export default { p { margin: 10px 15px; - line-height: 1.5; - font-style: italic; + font-size: 0.9rem; + opacity: 0.67; + line-height: 1.3; } } diff --git a/src/components/menus/MainMenu.vue b/src/components/menus/MainMenu.vue index a5a8ef84..85f2260a 100644 --- a/src/components/menus/MainMenu.vue +++ b/src/components/menus/MainMenu.vue @@ -84,25 +84,25 @@ Print
- - -
Settings
- Tweak application and keyboard shortcuts. + + +
Badges
+ List application features and earned badges. +
+ + +
Accounts
+ Manage access to your external accounts.
Templates
Configure Handlebars templates for your exports.
- - -
User accounts
- Manage access to your external accounts. -
- - -
Badges
- List application features and earned badges. + + +
Settings
+ Tweak application and keyboard shortcuts.

@@ -111,10 +111,8 @@ -
Reset application
- Sign out and clean all workspace data. + Reset application
-
About StackEdit @@ -218,7 +216,7 @@ export default { async reset() { try { await store.dispatch('modal/open', 'reset'); - window.location.href = '#reset=true'; + localStorage.setItem('resetStackEdit', '1'); window.location.reload(); } catch (e) { /* Cancel */ } }, diff --git a/src/components/menus/PublishMenu.vue b/src/components/menus/PublishMenu.vue index 4c959045..8655a107 100644 --- a/src/components/menus/PublishMenu.vue +++ b/src/components/menus/PublishMenu.vue @@ -4,9 +4,6 @@

{{currentFileName}} can't be published as it's a temporary file.

- +
@@ -181,8 +181,13 @@ export default { return tokensToArray(store.getters['data/zendeskTokensBySub']); }, noToken() { - return Object.values(store.getters['data/tokensByType']) - .every(tokens => !Object.keys(tokens).length); + return !this.bloggerTokens.length + && !this.dropboxTokens.length + && !this.githubTokens.length + && !this.gitlabTokens.length + && !this.googleDriveTokens.length + && !this.wordpressTokens.length + && !this.zendeskTokens.length; }, }, methods: { diff --git a/src/components/menus/SyncMenu.vue b/src/components/menus/SyncMenu.vue index 6c5451e4..e76e9889 100644 --- a/src/components/menus/SyncMenu.vue +++ b/src/components/menus/SyncMenu.vue @@ -4,9 +4,6 @@

{{currentFileName}} can't be synced as it's a temporary file.

- +
diff --git a/src/components/menus/WorkspaceBackupMenu.vue b/src/components/menus/WorkspaceBackupMenu.vue index 309f107c..d5281fc0 100644 --- a/src/components/menus/WorkspaceBackupMenu.vue +++ b/src/components/menus/WorkspaceBackupMenu.vue @@ -17,15 +17,19 @@ @@ -76,19 +86,24 @@ export default { .badge-entry { font-size: 0.8em; - margin: 0.75rem 0 0; - } - - svg { - width: 1.67em; - height: 1.67em; - margin-right: 0.25em; - opacity: 0.33; - flex: none; + margin: 0.75rem 0; } } -.badge-entry--earned svg { +.badge-entry__icon { + width: 1.67em; + height: 1.67em; + margin-right: 0.25em; + opacity: 0.3; + flex: none; +} + +.badge-entry__icon--some-earned { + opacity: 0.5; + color: goldenrod; +} + +.badge-entry__icon--earned { opacity: 1; color: goldenrod; } @@ -100,10 +115,10 @@ export default { .badge-entry__name { font-size: 1.2em; font-weight: bold; - opacity: 0.5; + opacity: 0.4; +} - .badge-entry--earned & { - opacity: 1; - } +.badge-entry__name--earned { + opacity: 1; } diff --git a/src/components/modals/WorkspaceManagementModal.vue b/src/components/modals/WorkspaceManagementModal.vue index 52120d58..3e9b49ac 100644 --- a/src/components/modals/WorkspaceManagementModal.vue +++ b/src/components/modals/WorkspaceManagementModal.vue @@ -4,7 +4,7 @@ -

The following workspaces are locally available:

+

The following workspaces are accessible:

@@ -48,11 +48,13 @@
+
+ + available offline + +
-