From 09147cacea6b80d348d4c8364b2815d9b4cac102 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Thu, 6 Dec 2018 20:34:00 +0700 Subject: add service worker and push notifications --- src/boot/after_store.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/boot/after_store.js') diff --git a/src/boot/after_store.js b/src/boot/after_store.js index a80baaf5..0c121fe2 100644 --- a/src/boot/after_store.js +++ b/src/boot/after_store.js @@ -17,16 +17,17 @@ import FollowRequests from '../components/follow_requests/follow_requests.vue' import OAuthCallback from '../components/oauth_callback/oauth_callback.vue' import UserSearch from '../components/user_search/user_search.vue' -const afterStoreSetup = ({store, i18n}) => { +const afterStoreSetup = ({ store, i18n }) => { window.fetch('/api/statusnet/config.json') .then((res) => res.json()) .then((data) => { - const {name, closed: registrationClosed, textlimit, server} = data.site + const { name, closed: registrationClosed, textlimit, server, vapidPublicKey } = data.site store.dispatch('setInstanceOption', { name: 'name', value: name }) store.dispatch('setInstanceOption', { name: 'registrationOpen', value: (registrationClosed === '0') }) store.dispatch('setInstanceOption', { name: 'textlimit', value: parseInt(textlimit) }) store.dispatch('setInstanceOption', { name: 'server', value: server }) + store.dispatch('setInstanceOption', { name: 'vapidPublicKey', value: vapidPublicKey }) var apiConfig = data.site.pleromafe -- cgit v1.2.3-70-g09d2 From ba188eddab7f6eb8747bc43c179a8478d4f2a5a4 Mon Sep 17 00:00:00 2001 From: Rinpatch Date: Sat, 8 Dec 2018 18:23:21 +0300 Subject: [pleroma#36] Add upload errors --- src/boot/after_store.js | 3 ++- src/components/media_upload/media_upload.js | 4 ++++ src/components/post_status_form/post_status_form.js | 5 +++++ src/components/post_status_form/post_status_form.vue | 2 +- src/i18n/en.json | 2 ++ 5 files changed, 14 insertions(+), 2 deletions(-) (limited to 'src/boot/after_store.js') diff --git a/src/boot/after_store.js b/src/boot/after_store.js index a80baaf5..38810326 100644 --- a/src/boot/after_store.js +++ b/src/boot/after_store.js @@ -21,11 +21,12 @@ const afterStoreSetup = ({store, i18n}) => { window.fetch('/api/statusnet/config.json') .then((res) => res.json()) .then((data) => { - const {name, closed: registrationClosed, textlimit, server} = data.site + const {name, closed: registrationClosed, textlimit, uploadlimit, server} = data.site store.dispatch('setInstanceOption', { name: 'name', value: name }) store.dispatch('setInstanceOption', { name: 'registrationOpen', value: (registrationClosed === '0') }) store.dispatch('setInstanceOption', { name: 'textlimit', value: parseInt(textlimit) }) + store.dispatch('setInstanceOption', { name: 'uploadlimit', value: parseInt(uploadlimit) }) store.dispatch('setInstanceOption', { name: 'server', value: server }) var apiConfig = data.site.pleromafe diff --git a/src/components/media_upload/media_upload.js b/src/components/media_upload/media_upload.js index 66337c3f..c2f3c3c7 100644 --- a/src/components/media_upload/media_upload.js +++ b/src/components/media_upload/media_upload.js @@ -21,6 +21,10 @@ const mediaUpload = { uploadFile (file) { const self = this const store = this.$store + if (file.size > store.state.instance.uploadlimit) { + self.$emit('upload-failed', 'upload_error_file_too_big') + return + } const formData = new FormData() formData.append('media', file) diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js index 789243cf..f7ba3cd5 100644 --- a/src/components/post_status_form/post_status_form.js +++ b/src/components/post_status_form/post_status_form.js @@ -262,6 +262,11 @@ const PostStatusForm = { let index = this.newStatus.files.indexOf(fileInfo) this.newStatus.files.splice(index, 1) }, + uploadFailed (errString) { + errString = errString || 'upload_error' + this.error = this.$t('post_status.' + errString) + this.enableSubmit() + }, disableSubmit () { this.submitDisabled = true }, diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue index e4c46b9a..59ae9af4 100644 --- a/src/components/post_status_form/post_status_form.vue +++ b/src/components/post_status_form/post_status_form.vue @@ -64,7 +64,7 @@
- +

{{ charactersLeft }}

{{ charactersLeft }}

diff --git a/src/i18n/en.json b/src/i18n/en.json index 44291ad0..93a24743 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -52,6 +52,8 @@ "account_not_locked_warning": "Your account is not {0}. Anyone can follow you to view your follower-only posts.", "account_not_locked_warning_link": "locked", "attachments_sensitive": "Mark attachments as sensitive", + "upload_error": "Upload failed.", + "upload_error_file_too_big": "Upload failed. File too big", "content_type": { "plain_text": "Plain text" }, -- cgit v1.2.3-70-g09d2 From 788383d8a1e10abe7f9848b95bf7eb284f1113cd Mon Sep 17 00:00:00 2001 From: rinpatch Date: Sat, 8 Dec 2018 21:56:00 +0100 Subject: Make uploadlimit an object that stores upload limits for avatars, banners, backgrounds, general content --- src/boot/after_store.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/boot/after_store.js') diff --git a/src/boot/after_store.js b/src/boot/after_store.js index 38810326..6a7669ce 100644 --- a/src/boot/after_store.js +++ b/src/boot/after_store.js @@ -26,7 +26,10 @@ const afterStoreSetup = ({store, i18n}) => { store.dispatch('setInstanceOption', { name: 'name', value: name }) store.dispatch('setInstanceOption', { name: 'registrationOpen', value: (registrationClosed === '0') }) store.dispatch('setInstanceOption', { name: 'textlimit', value: parseInt(textlimit) }) - store.dispatch('setInstanceOption', { name: 'uploadlimit', value: parseInt(uploadlimit) }) + store.dispatch('setInstanceOption', { name: 'uploadlimit', value: parseInt(uploadlimit.uploadlimit) }) + store.dispatch('setInstanceOption', { name: 'avatarlimit', value: parseInt(uploadlimit.avatarlimit) }) + store.dispatch('setInstanceOption', { name: 'backgroundlimit', value: parseInt(uploadlimit.backgroundlimit) }) + store.dispatch('setInstanceOption', { name: 'bannerlimit', value: parseInt(uploadlimit.bannerlimit) }) store.dispatch('setInstanceOption', { name: 'server', value: server }) var apiConfig = data.site.pleromafe -- cgit v1.2.3-70-g09d2 From ee70ec4c7efb49c08f0a76b6b2694c0e9910978c Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Mon, 10 Dec 2018 22:36:25 +0700 Subject: fix race condition --- src/boot/after_store.js | 5 ++++- src/main.js | 11 ++++++++--- src/modules/pushNotifications.js | 36 ------------------------------------ src/modules/users.js | 13 +++++++++---- 4 files changed, 21 insertions(+), 44 deletions(-) delete mode 100644 src/modules/pushNotifications.js (limited to 'src/boot/after_store.js') diff --git a/src/boot/after_store.js b/src/boot/after_store.js index 0c121fe2..0d1cabd5 100644 --- a/src/boot/after_store.js +++ b/src/boot/after_store.js @@ -27,7 +27,10 @@ const afterStoreSetup = ({ store, i18n }) => { store.dispatch('setInstanceOption', { name: 'registrationOpen', value: (registrationClosed === '0') }) store.dispatch('setInstanceOption', { name: 'textlimit', value: parseInt(textlimit) }) store.dispatch('setInstanceOption', { name: 'server', value: server }) - store.dispatch('setInstanceOption', { name: 'vapidPublicKey', value: vapidPublicKey }) + + if (vapidPublicKey) { + store.dispatch('setInstanceOption', { name: 'vapidPublicKey', value: vapidPublicKey }) + } var apiConfig = data.site.pleromafe diff --git a/src/main.js b/src/main.js index 91592191..e4621482 100644 --- a/src/main.js +++ b/src/main.js @@ -10,7 +10,6 @@ import apiModule from './modules/api.js' import configModule from './modules/config.js' import chatModule from './modules/chat.js' import oauthModule from './modules/oauth.js' -import pushNotificationsModule from './modules/pushNotifications.js' import VueTimeago from 'vue-timeago' import VueI18n from 'vue-i18n' @@ -61,13 +60,19 @@ createPersistedState(persistedStateOptions).then((persistedState) => { api: apiModule, config: configModule, chat: chatModule, - oauth: oauthModule, - pushNotifications: pushNotificationsModule + oauth: oauthModule }, plugins: [persistedState], strict: false // Socket modifies itself, let's ignore this for now. // strict: process.env.NODE_ENV !== 'production' }) + store.subscribe((mutation, state) => { + if ((mutation.type === 'setCurrentUser' && state.instance.vapidPublicKey) || // Login + existing key + (mutation.type === 'setInstanceOption' && mutation.payload.name === 'vapidPublicKey' && state.users.currentUser)) { // Logged in, key arrives late + store.dispatch('registerPushNotifications') + } + }) + afterStoreSetup({ store, i18n }) }) diff --git a/src/modules/pushNotifications.js b/src/modules/pushNotifications.js deleted file mode 100644 index ea92f811..00000000 --- a/src/modules/pushNotifications.js +++ /dev/null @@ -1,36 +0,0 @@ -import registerPushNotifications from '../services/push/push.js' - -const subscribe = { - state: { - token: null, - vapidPublicKey: null - }, - mutations: { - setApiToken (state, user) { - state.token = user.credentials - }, - setVapidPublicKey (state, vapidPublicKey) { - state.vapidPublicKey = vapidPublicKey - } - }, - actions: { - setInstanceOption (store, { name, value }) { - if (name === 'vapidPublicKey') { - store.commit('setVapidPublicKey', value) - - if (store.state.token) { - registerPushNotifications(store.rootState.config.webPushNotifications, value, store.state.token) - } - } - }, - setCurrentUser (store, user) { - store.commit('setApiToken', user.credentials) - - if (store.state.vapidPublicKey) { - registerPushNotifications(store.rootState.config.webPushNotifications, store.state.vapidPublicKey, user.credentials) - } - } - } -} - -export default subscribe diff --git a/src/modules/users.js b/src/modules/users.js index 1256e9df..5e0c087d 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -1,6 +1,7 @@ import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js' import { compact, map, each, merge } from 'lodash' import { set } from 'vue' +import registerPushNotifications from '../services/push/push.js' // TODO: Unify with mergeOrAdd in statuses.js export const mergeOrAdd = (arr, obj, item) => { @@ -65,6 +66,13 @@ const users = { store.rootState.api.backendInteractor.fetchUser({id}) .then((user) => store.commit('addNewUsers', user)) }, + registerPushNotifications (store) { + const token = store.state.currentUser.credentials + const vapidPublicKey = store.rootState.instance.vapidPublicKey + const isEnabled = store.rootState.config.webPushNotifications + + registerPushNotifications(isEnabled, vapidPublicKey, token) + }, addNewStatuses (store, { statuses }) { const users = map(statuses, 'user') const retweetedUsers = compact(map(statuses, 'retweeted_status.user')) @@ -86,9 +94,6 @@ const users = { store.dispatch('stopFetching', 'friends') store.commit('setBackendInteractor', backendInteractorService()) }, - setCurrentUser (store, user) { - store.commit('setCurrentUser', user) - }, loginUser (store, accessToken) { return new Promise((resolve, reject) => { const commit = store.commit @@ -100,7 +105,7 @@ const users = { .then((user) => { // user.credentials = userCredentials user.credentials = accessToken - store.dispatch('setCurrentUser', user) + commit('setCurrentUser', user) commit('addNewUsers', [user]) // Set our new backend interactor -- cgit v1.2.3-70-g09d2 From b839ba7870c2872607ebf3ae41a8c08f17a7dde7 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Tue, 11 Dec 2018 18:45:25 +0300 Subject: Quality of Frontend Developer's Life: here to stay --- README.md | 9 +++++++++ build/webpack.dev.conf.js | 4 +++- build/webpack.prod.conf.js | 12 +++++++++--- config/index.js | 19 +++++++++++++++---- src/boot/after_store.js | 11 ++++++++++- src/main.js | 6 ++++++ 6 files changed, 52 insertions(+), 9 deletions(-) (limited to 'src/boot/after_store.js') diff --git a/README.md b/README.md index b6e5a586..181b6a0d 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,15 @@ npm run build npm run unit ``` +# For Contributors: + +You can create file `/config/local.json` (see [example](https://git.pleroma.social/pleroma/pleroma-fe/blob/develop/config/local.example.json)) to enable some convenience dev options: + +* `target`: makes local dev server redirect to some existing instance's BE instead of local BE, useful for testing things in near-production environment and searching for real-life use-cases. +* `staticConfigPreference`: makes FE's `/static/config.json` take preference of BE-served `/api/statusnet/config.json`. Only works in dev mode. + +FE Build process also leaves current commit hash in global variable `___pleromafe_commit_hash` so that you can easily see which pleroma-fe commit instance is running, also helps pinpointing which commit was used when FE was bundled into BE. + # Configuration Edit config.json for configuration. scopeOptionsEnabled gives you input fields for CWs and the scope settings. diff --git a/build/webpack.dev.conf.js b/build/webpack.dev.conf.js index 7e1a104f..9f34619c 100644 --- a/build/webpack.dev.conf.js +++ b/build/webpack.dev.conf.js @@ -18,7 +18,9 @@ module.exports = merge(baseWebpackConfig, { devtool: '#eval-source-map', plugins: [ new webpack.DefinePlugin({ - 'process.env': config.dev.env + 'process.env': config.dev.env, + 'COMMIT_HASH': JSON.stringify('DEV'), + 'DEV_OVERRIDES': JSON.stringify(config.dev.settings) }), // https://github.com/glenjamin/webpack-hot-middleware#installation--usage new webpack.optimize.OccurenceOrderPlugin(), diff --git a/build/webpack.prod.conf.js b/build/webpack.prod.conf.js index 6119f700..b2c87e6c 100644 --- a/build/webpack.prod.conf.js +++ b/build/webpack.prod.conf.js @@ -7,8 +7,13 @@ var baseWebpackConfig = require('./webpack.base.conf') var ExtractTextPlugin = require('extract-text-webpack-plugin') var HtmlWebpackPlugin = require('html-webpack-plugin') var env = process.env.NODE_ENV === 'testing' - ? require('../config/test.env') - : config.build.env + ? require('../config/test.env') + : config.build.env + +let commitHash = require('child_process') + .execSync('git rev-parse --short HEAD') + .toString(); +console.log(commitHash) var webpackConfig = merge(baseWebpackConfig, { module: { @@ -29,7 +34,8 @@ var webpackConfig = merge(baseWebpackConfig, { plugins: [ // http://vuejs.github.io/vue-loader/workflow/production.html new webpack.DefinePlugin({ - 'process.env': env + 'process.env': env, + 'COMMIT_HASH': JSON.stringify(commitHash) }), new webpack.optimize.UglifyJsPlugin({ compress: { diff --git a/config/index.js b/config/index.js index 7b0ef26c..56fa5940 100644 --- a/config/index.js +++ b/config/index.js @@ -1,5 +1,15 @@ // see http://vuejs-templates.github.io/webpack for documentation. -var path = require('path') +const path = require('path') +let settings = {} +try { + settings = require('./local.json') + console.log('Using local dev server settings (/config/local.json):') + console.log(JSON.stringify(settings, null, 2)) +} catch (e) { + console.log('Local dev server settings not found (/config/local.json)') +} + +const target = settings.target || 'http://localhost:4000/' module.exports = { build: { @@ -19,21 +29,22 @@ module.exports = { dev: { env: require('./dev.env'), port: 8080, + settings, assetsSubDirectory: 'static', assetsPublicPath: '/', proxyTable: { '/api': { - target: 'http://localhost:4000/', + target, changeOrigin: true, cookieDomainRewrite: 'localhost' }, '/nodeinfo': { - target: 'http://localhost:4000/', + target, changeOrigin: true, cookieDomainRewrite: 'localhost' }, '/socket': { - target: 'http://localhost:4000/', + target, changeOrigin: true, cookieDomainRewrite: 'localhost', ws: true diff --git a/src/boot/after_store.js b/src/boot/after_store.js index a80baaf5..9ce2d7ed 100644 --- a/src/boot/after_store.js +++ b/src/boot/after_store.js @@ -38,8 +38,17 @@ const afterStoreSetup = ({store, i18n}) => { return {} }) .then((staticConfig) => { + const overrides = window.___pleromafe_dev_overrides || {} + const env = window.___pleromafe_mode.NODE_ENV + // This takes static config and overrides properties that are present in apiConfig - var config = Object.assign({}, staticConfig, apiConfig) + let config = {} + if (overrides.staticConfigPreference && env === 'DEV') { + console.warn('OVERRIDING API CONFIG WITH STATIC CONFIG') + config = Object.assign({}, apiConfig, staticConfig) + } else { + config = Object.assign({}, staticConfig, apiConfig) + } var theme = (config.theme) var background = (config.background) diff --git a/src/main.js b/src/main.js index 378fe95c..7f3746c8 100644 --- a/src/main.js +++ b/src/main.js @@ -69,3 +69,9 @@ createPersistedState(persistedStateOptions).then((persistedState) => { afterStoreSetup({store, i18n}) }) + +// These are inlined by webpack's DefinePlugin +/* eslint-disable */ +window.___pleromafe_mode = process.env +window.___pleromafe_commit_hash = COMMIT_HASH +window.___pleromafe_dev_overrides = DEV_OVERRIDES -- cgit v1.2.3-70-g09d2 From c54eb1ecad33c4e45868ca35bcaa5404a1bfd0cd Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Tue, 11 Dec 2018 19:01:08 +0300 Subject: fix --- src/boot/after_store.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/boot/after_store.js') diff --git a/src/boot/after_store.js b/src/boot/after_store.js index 9ce2d7ed..4374ce8e 100644 --- a/src/boot/after_store.js +++ b/src/boot/after_store.js @@ -43,7 +43,7 @@ const afterStoreSetup = ({store, i18n}) => { // This takes static config and overrides properties that are present in apiConfig let config = {} - if (overrides.staticConfigPreference && env === 'DEV') { + if (overrides.staticConfigPreference && env === 'development') { console.warn('OVERRIDING API CONFIG WITH STATIC CONFIG') config = Object.assign({}, apiConfig, staticConfig) } else { -- cgit v1.2.3-70-g09d2 From f87001c22f8c85bddb78c975f0bc22b8bfdcd27c Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Thu, 13 Dec 2018 20:25:46 +0300 Subject: fix old MR --- src/boot/after_store.js | 4 ++++ src/main.js | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'src/boot/after_store.js') diff --git a/src/boot/after_store.js b/src/boot/after_store.js index 07337595..a8594a64 100644 --- a/src/boot/after_store.js +++ b/src/boot/after_store.js @@ -28,6 +28,10 @@ const afterStoreSetup = ({ store, i18n }) => { store.dispatch('setInstanceOption', { name: 'textlimit', value: parseInt(textlimit) }) store.dispatch('setInstanceOption', { name: 'server', value: server }) + if (data.nsfwCensorImage) { + store.dispatch('setInstanceOption', { name: 'nsfwCensorImage', value: data.nsfwCensorImage }) + } + if (vapidPublicKey) { store.dispatch('setInstanceOption', { name: 'vapidPublicKey', value: vapidPublicKey }) } diff --git a/src/main.js b/src/main.js index 6ce2df13..bf92e78e 100644 --- a/src/main.js +++ b/src/main.js @@ -60,9 +60,6 @@ const registerPushNotifications = store => { if (isUserMutation && vapidPublicKey && permission) { return store.dispatch('registerPushNotifications') } - if (data['nsfwCensorImage']) { - store.dispatch('setOption', { name: 'nsfwCensorImage', value: data['nsfwCensorImage'] }) - } const user = state.users.currentUser const isVapidMutation = mutation.type === 'setInstanceOption' && mutation.payload.name === 'vapidPublicKey' -- cgit v1.2.3-70-g09d2