Przeglądaj źródła

feat(vpaas): Add endpoint counter & remove branding on vpaas meetings

master
Vlad Piersec 4 lat temu
rodzic
commit
71d0577a49

+ 6
- 0
react/features/app/actions.js Wyświetl plik

@@ -24,6 +24,7 @@ import {
24 24
     parseURIString,
25 25
     toURLString
26 26
 } from '../base/util';
27
+import { isVpaasMeeting } from '../billing-counter/functions';
27 28
 import { clearNotifications, showNotification } from '../notifications';
28 29
 import { setFatalError } from '../overlay';
29 30
 
@@ -291,7 +292,12 @@ export function maybeRedirectToWelcomePage(options: Object = {}) {
291 292
 
292 293
         // if close page is enabled redirect to it, without further action
293 294
         if (enableClosePage) {
295
+            if (isVpaasMeeting(getState())) {
296
+                redirectToStaticPage('/');
297
+            }
298
+
294 299
             const { isGuest, jwt } = getState()['features/base/jwt'];
300
+
295 301
             let hashParam;
296 302
 
297 303
             // save whether current user is guest or not, and pass auth token,

+ 1
- 0
react/features/app/middlewares.any.js Wyświetl plik

@@ -18,6 +18,7 @@ import '../base/sounds/middleware';
18 18
 import '../base/testing/middleware';
19 19
 import '../base/tracks/middleware';
20 20
 import '../base/user-interaction/middleware';
21
+import '../billing-counter/middleware';
21 22
 import '../calendar-sync/middleware';
22 23
 import '../chat/middleware';
23 24
 import '../conference/middleware';

+ 47
- 8
react/features/base/react/components/web/Watermarks.js Wyświetl plik

@@ -2,9 +2,11 @@
2 2
 
3 3
 import React, { Component } from 'react';
4 4
 
5
+import { isVpaasMeeting } from '../../../../billing-counter/functions';
5 6
 import { translate } from '../../../i18n';
6 7
 import { connect } from '../../../redux';
7 8
 
9
+
8 10
 declare var interfaceConfig: Object;
9 11
 
10 12
 /**
@@ -36,6 +38,11 @@ type Props = {
36 38
      */
37 39
     _isGuest: boolean,
38 40
 
41
+    /**
42
+     * Whether or not the current meeting is a vpaas one.
43
+     */
44
+    _isVpaas: boolean,
45
+
39 46
     /**
40 47
      * Flag used to signal that the logo can be displayed.
41 48
      * It becomes true after the user customization options are fetched.
@@ -181,6 +188,33 @@ class Watermarks extends Component<Props, State> {
181 188
             || _welcomePageIsVisible;
182 189
     }
183 190
 
191
+    /**
192
+     * Returns the background image style.
193
+     *
194
+     * @private
195
+     * @returns {string}
196
+     */
197
+    _getBackgroundImageStyle() {
198
+        const {
199
+            _customLogoUrl,
200
+            _isVpaas,
201
+            defaultJitsiLogoURL
202
+        } = this.props;
203
+        let style = 'none';
204
+
205
+        if (_isVpaas) {
206
+            if (_customLogoUrl) {
207
+                style = `url(${_customLogoUrl})`;
208
+            }
209
+        } else {
210
+            style = `url(${_customLogoUrl
211
+                || defaultJitsiLogoURL
212
+                || interfaceConfig.DEFAULT_LOGO_URL})`;
213
+        }
214
+
215
+        return style;
216
+    }
217
+
184 218
     /**
185 219
      * Renders a brand watermark if it is enabled.
186 220
      *
@@ -221,18 +255,22 @@ class Watermarks extends Component<Props, State> {
221 255
      */
222 256
     _renderJitsiWatermark() {
223 257
         let reactElement = null;
224
-        const {
225
-            _customLogoUrl,
226
-            _customLogoLink,
227
-            defaultJitsiLogoURL
228
-        } = this.props;
229 258
 
230 259
         if (this._canDisplayJitsiWatermark()) {
231
-            const link = _customLogoLink || this.state.jitsiWatermarkLink;
260
+            const backgroundImage = this._getBackgroundImageStyle();
261
+            const link = this.props._customLogoLink || this.state.jitsiWatermarkLink;
262
+            const additionalStyles = {};
263
+
264
+            if (backgroundImage === 'none') {
265
+                additionalStyles.height = 0;
266
+                additionalStyles.width = 0;
267
+            }
268
+
232 269
             const style = {
233
-                backgroundImage: `url(${_customLogoUrl || defaultJitsiLogoURL || interfaceConfig.DEFAULT_LOGO_URL})`,
270
+                backgroundImage,
234 271
                 maxWidth: 140,
235
-                maxHeight: 70
272
+                maxHeight: 70,
273
+                ...additionalStyles
236 274
             };
237 275
 
238 276
             reactElement = (<div
@@ -299,6 +337,7 @@ function _mapStateToProps(state) {
299 337
         _customLogoLink: logoClickUrl,
300 338
         _customLogoUrl: logoImageUrl,
301 339
         _isGuest: isGuest,
340
+        _isVpaas: isVpaasMeeting(state),
302 341
         _readyToDisplayJitsiWatermark: customizationReady,
303 342
         _welcomePageIsVisible: !room
304 343
     };

+ 4
- 0
react/features/billing-counter/actionTypes.js Wyświetl plik

@@ -0,0 +1,4 @@
1
+/**
2
+ * Action used to store the billing id.
3
+ */
4
+export const SET_BILLING_ID = 'SET_BILLING_ID';

+ 51
- 0
react/features/billing-counter/actions.js Wyświetl plik

@@ -0,0 +1,51 @@
1
+// @flow
2
+
3
+import uuid from 'uuid';
4
+
5
+import { SET_BILLING_ID } from './actionTypes';
6
+import { extractVpaasTenantFromPath, getBillingId, sendCountRequest } from './functions';
7
+
8
+/**
9
+ * Sends a billing count request when needed.
10
+ * If there is no billingId, it presists one first and sends the request after.
11
+ *
12
+ * @returns {Function}
13
+ */
14
+export function countEndpoint() {
15
+    return function(dispatch: Function, getState: Function) {
16
+        const state = getState();
17
+        const baseUrl = state['features/base/config'].billingCounterUrl;
18
+        const jwt = state['features/base/jwt'].jwt;
19
+        const tenant = extractVpaasTenantFromPath(state['features/base/connection'].locationURL.pathname);
20
+        const shouldSendRequest = Boolean(baseUrl && jwt && tenant);
21
+
22
+        if (shouldSendRequest) {
23
+            let billingId = getBillingId();
24
+
25
+            if (!billingId) {
26
+                billingId = uuid.v4();
27
+                dispatch(setBillingId(billingId));
28
+            }
29
+
30
+            sendCountRequest({
31
+                baseUrl,
32
+                billingId,
33
+                jwt,
34
+                tenant
35
+            });
36
+        }
37
+    };
38
+}
39
+
40
+/**
41
+ * Action used to set the user billing id.
42
+ *
43
+ * @param {string} value - The uid.
44
+ * @returns {Object}
45
+ */
46
+function setBillingId(value) {
47
+    return {
48
+        type: SET_BILLING_ID,
49
+        value
50
+    };
51
+}

+ 9
- 0
react/features/billing-counter/constants.js Wyświetl plik

@@ -0,0 +1,9 @@
1
+/**
2
+ * The key for the billing id stored in localStorage.
3
+ */
4
+export const BILLING_ID = 'billingId';
5
+
6
+/**
7
+ * The prefix for the vpaas tenant.
8
+ */
9
+export const VPAAS_TENANT_PREFIX = 'vpass-magic-cookie-';

+ 91
- 0
react/features/billing-counter/functions.js Wyświetl plik

@@ -0,0 +1,91 @@
1
+// @flow
2
+
3
+import { jitsiLocalStorage } from '@jitsi/js-utils';
4
+
5
+import { BILLING_ID, VPAAS_TENANT_PREFIX } from './constants';
6
+import logger from './logger';
7
+
8
+/**
9
+ * Returns the full vpaas tenant if available, given a path.
10
+ *
11
+ * @param {string} path - The meeting url path.
12
+ * @returns {string}
13
+ */
14
+export function extractVpaasTenantFromPath(path: string) {
15
+    const [ , tenant ] = path.split('/');
16
+
17
+    if (tenant.startsWith(VPAAS_TENANT_PREFIX)) {
18
+        return tenant;
19
+    }
20
+
21
+    return '';
22
+}
23
+
24
+/**
25
+ * Returns true if the current meeting is a vpaas one.
26
+ *
27
+ * @param {Object} state - The state of the app.
28
+ * @returns {boolean}
29
+ */
30
+export function isVpaasMeeting(state: Object) {
31
+    return Boolean(
32
+        state['features/base/config'].billingCounterUrl
33
+        && state['features/base/jwt'].jwt
34
+        && extractVpaasTenantFromPath(
35
+            state['features/base/connection'].locationURL.pathname)
36
+    );
37
+}
38
+
39
+/**
40
+ * Sends a billing counter request.
41
+ *
42
+ * @param {Object} reqData - The request info.
43
+ * @param {string} reqData.baseUrl - The base url for the request.
44
+ * @param {string} billingId - The unique id of the client.
45
+ * @param {string} jwt - The JWT token.
46
+ * @param {string} tenat - The client tenant.
47
+ * @returns {void}
48
+ */
49
+export async function sendCountRequest({ baseUrl, billingId, jwt, tenant }: {
50
+    baseUrl: string,
51
+    billingId: string,
52
+    jwt: string,
53
+    tenant: string
54
+}) {
55
+    const fullUrl = `${baseUrl}/${encodeURIComponent(tenant)}/${billingId}`;
56
+    const headers = {
57
+        'Authorization': `Bearer: ${jwt}`
58
+    };
59
+
60
+    try {
61
+        const res = await fetch(fullUrl, {
62
+            method: 'GET',
63
+            headers
64
+        });
65
+
66
+        if (!res.ok) {
67
+            logger.error('Status error:', res.status);
68
+        }
69
+    } catch (err) {
70
+        logger.error('Could not send request', err);
71
+    }
72
+}
73
+
74
+/**
75
+ * Returns the stored billing id.
76
+ *
77
+ * @returns {string}
78
+ */
79
+export function getBillingId() {
80
+    return jitsiLocalStorage.getItem(BILLING_ID);
81
+}
82
+
83
+/**
84
+ * Stores the billing id.
85
+ *
86
+ * @param {string} value - The id to be stored.
87
+ * @returns {void}
88
+ */
89
+export function setBillingId(value: string) {
90
+    jitsiLocalStorage.setItem(BILLING_ID, value);
91
+}

+ 5
- 0
react/features/billing-counter/logger.js Wyświetl plik

@@ -0,0 +1,5 @@
1
+// @flow
2
+
3
+import { getLogger } from '../base/logging/functions';
4
+
5
+export default getLogger('features/billing-counter');

+ 31
- 0
react/features/billing-counter/middleware.js Wyświetl plik

@@ -0,0 +1,31 @@
1
+import { CONFERENCE_JOINED } from '../base/conference/actionTypes';
2
+import { MiddlewareRegistry } from '../base/redux';
3
+
4
+import { SET_BILLING_ID } from './actionTypes';
5
+import { countEndpoint } from './actions';
6
+import { setBillingId } from './functions';
7
+
8
+/**
9
+ * The redux middleware for billing counter.
10
+ *
11
+ * @param {Store} store - The redux store.
12
+ * @returns {Function}
13
+ */
14
+MiddlewareRegistry.register(store => next => async action => {
15
+    switch (action.type) {
16
+    case SET_BILLING_ID: {
17
+        setBillingId(action.value);
18
+
19
+        break;
20
+    }
21
+
22
+    case CONFERENCE_JOINED: {
23
+        store.dispatch(countEndpoint());
24
+
25
+        break;
26
+    }
27
+
28
+    }
29
+
30
+    return next(action);
31
+});

+ 10
- 2
react/features/chrome-extension-banner/components/ChromeExtensionBanner.web.js Wyświetl plik

@@ -16,6 +16,7 @@ import { translate } from '../../base/i18n';
16 16
 import { Icon, IconClose } from '../../base/icons';
17 17
 import { browser } from '../../base/lib-jitsi-meet';
18 18
 import { connect } from '../../base/redux';
19
+import { isVpaasMeeting } from '../../billing-counter/functions';
19 20
 import logger from '../logger';
20 21
 
21 22
 
@@ -50,6 +51,11 @@ type Props = {
50 51
      */
51 52
     iAmRecorder: boolean,
52 53
 
54
+    /**
55
+     * Whether it's a vpaas meeting or not.
56
+     */
57
+    isVpaas: boolean,
58
+
53 59
     /**
54 60
      * Invoked to obtain translated strings.
55 61
      */
@@ -146,7 +152,8 @@ class ChromeExtensionBanner extends PureComponent<Props, State> {
146 152
     _isSupportedEnvironment() {
147 153
         return interfaceConfig.SHOW_CHROME_EXTENSION_BANNER
148 154
             && browser.isChrome()
149
-            && !isMobileBrowser();
155
+            && !isMobileBrowser()
156
+            && !this.props.isVpaas;
150 157
     }
151 158
 
152 159
     _onClosePressed: () => void;
@@ -280,7 +287,8 @@ const _mapStateToProps = state => {
280 287
         // Using emptyObject so that we don't change the reference every time when _mapStateToProps is called.
281 288
         bannerCfg: state['features/base/config'].chromeExtensionBanner || emptyObject,
282 289
         conference: getCurrentConference(state),
283
-        iAmRecorder: state['features/base/config'].iAmRecorder
290
+        iAmRecorder: state['features/base/config'].iAmRecorder,
291
+        isVpaas: isVpaasMeeting(state)
284 292
     };
285 293
 };
286 294
 

+ 11
- 2
react/features/recording/components/Recording/StartRecordingDialogContent.js Wyświetl plik

@@ -21,6 +21,7 @@ import {
21 21
 } from '../../../base/react';
22 22
 import { connect } from '../../../base/redux';
23 23
 import { ColorPalette, StyleType } from '../../../base/styles';
24
+import { isVpaasMeeting } from '../../../billing-counter/functions';
24 25
 import { authorizeDropbox, updateDropboxToken } from '../../../dropbox';
25 26
 import { RECORDING_TYPES } from '../../constants';
26 27
 import { getRecordingDurationEstimation } from '../../functions';
@@ -72,6 +73,11 @@ type Props = {
72 73
      */
73 74
     isValidating: boolean,
74 75
 
76
+    /**
77
+     * Whether or not the current meeting is a vpaas one.
78
+     */
79
+    isVpaas: boolean,
80
+
75 81
     /**
76 82
      * The function will be called when there are changes related to the
77 83
      * switches.
@@ -226,7 +232,7 @@ class StartRecordingDialogContent extends Component<Props> {
226 232
             return null;
227 233
         }
228 234
 
229
-        const { _dialogStyles, _styles: styles, isValidating, t } = this.props;
235
+        const { _dialogStyles, _styles: styles, isValidating, isVpaas, t } = this.props;
230 236
 
231 237
         const switchContent
232 238
             = this.props.integrationsEnabled
@@ -240,6 +246,8 @@ class StartRecordingDialogContent extends Component<Props> {
240 246
                         value = { this.props.selectedRecordingService === RECORDING_TYPES.JITSI_REC_SERVICE } />
241 247
                 ) : null;
242 248
 
249
+        const icon = isVpaas ? ICON_SHARE : JITSI_LOGO;
250
+
243 251
         return (
244 252
             <Container
245 253
                 className = 'recording-header'
@@ -248,7 +256,7 @@ class StartRecordingDialogContent extends Component<Props> {
248 256
                 <Container className = 'recording-icon-container'>
249 257
                     <Image
250 258
                         className = 'recording-icon'
251
-                        src = { JITSI_LOGO }
259
+                        src = { icon }
252 260
                         style = { styles.recordingIcon } />
253 261
                 </Container>
254 262
                 <Text
@@ -484,6 +492,7 @@ class StartRecordingDialogContent extends Component<Props> {
484 492
 function _mapStateToProps(state) {
485 493
     return {
486 494
         ..._abstractMapStateToProps(state),
495
+        isVpaas: isVpaasMeeting(state),
487 496
         _styles: ColorSchemeRegistry.get(state, 'StartRecordingDialogContent')
488 497
     };
489 498
 }

Ładowanie…
Anuluj
Zapisz