Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ with the following top-level properties:
| `canChat` | bool | Optional | `true` | Whether the user can be offered chat or not. |
| `layout` | string | Optional | `max-width-fixed-height` | The chat layout `max-width-fixed-height`\|`max-parent-size`\|`panel-fixed-size`\|`panel-max-parent-size` |
| `nodeId` | string | Mandatory | `null` | The id of the HTMLNode where Happychat will be rendered. |
| `theme` | string | Optional | `calypso` | Color theme. Valid values are `calypso`, `woo`, and `woo`

### The entry prop

Expand Down
4 changes: 2 additions & 2 deletions docs/HACKING.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ Upon the iframe creation a spinner line is shown right away within the iframe -a

We've transitioned to a codebase that supports themes by consolidating the colors used and using CSS Custom Properties. At the time of writing we support 3 themes, that may be found at `src/ui/css/themes`:

- `main`: follows the [WordPress.com guidelines](https://wordpress.com/design-handbook/colors/). It's the default theme.
- `calypso`: follows the [WordPress.com guidelines](https://wordpress.com/design-handbook/colors/). It's the default theme.
- `jpop`: follows the Jetpack guidelines.
- `woo`: follows the [WooCommerce guidelines](https://woocommerce.com/style-guide/#sg-palette).

All SCSS color variables are declared at `/home/andres/src/happychat-client/src/ui/css/shared/_colors.scss`. The themes are automatically selected depending on the the chat group the user is routed to. For example, the `woo` theme will be activated when group is `woo`, and `jpop` when group is `jpop`.
All SCSS color variables are declared at `/home/andres/src/happychat-client/src/ui/css/shared/_colors.scss`. The themes are selected based on the `theme` parameter sent, the default theme is `calypso`

Note that CSS Custom Properties support is yet not [ubiquitous](https://caniuse.com/#feat=css-variables) -current offenders are IE11 and Opera Mini- so we use [postcss-custom-properties](https://github.com/postcss/postcss-custom-properties) processors to compile back for those browsers.

Expand Down
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@
"dev:standalone:js": "NODE_ENV=development webpack-dev-server --config webpack.standalone.config.js",
"dev:standalone:css": "run-p dev:standalone:css:*",
"dev:standalone:css:main": "node-sass src/form.scss | postcss --config postcss.config.json -u autoprefixer -u postcss-custom-properties --no-map -o targets/standalone/happychat.css",
"dev:standalone:css:calypso": "node-sass src/ui/css/themes/_calypso.scss | postcss --config postcss.config.json -u autoprefixer -u postcss-custom-properties --no-map -o targets/standalone/calypso.css",
"dev:standalone:css:woo": "node-sass src/ui/css/themes/_woo.scss | postcss --config postcss.config.json -u autoprefixer -u postcss-custom-properties --no-map -o targets/standalone/woo.css",
"dev:standalone:css:jpop": "node-sass src/ui/css/themes/_jpop.scss | postcss --config postcss.config.json -u autoprefixer -u postcss-custom-properties --no-map -o targets/standalone/jpop.css",

"dev:npm": "run-p dev:npm:*",
"dev:npm:js": "NODE_ENV=development ./node_modules/babel-cli/bin/babel.js --watch src --out-dir targets/npm",
"dev:npm:css": "run-p dev:npm:css:*",
"dev:npm:css:main": "node-sass src/form.scss | postcss --config postcss.config.json -u autoprefixer -u postcss-custom-properties --no-map -o targets/npm/happychat.css",
"dev:npm:css:calypso": "node-sass src/ui/css/themes/_calypso.scss | postcss --config postcss.config.json -u autoprefixer -u postcss-custom-properties --no-map -o targets/npm/calypso.css",
"dev:npm:css:woo": "node-sass src/ui/css/themes/_woo.scss | postcss --config postcss.config.json -u autoprefixer -u postcss-custom-properties --no-map -o targets/npm/woo.css",
"dev:npm:css:jpop": "node-sass src/ui/css/themes/_jpop.scss | postcss --config postcss.config.json -u autoprefixer -u postcss-custom-properties --no-map -o targets/npm/jpop.css",
"dev:npm:css:serve": "NODE_ENV=development webpack-dev-server --config webpack.npm.config.js",
Expand All @@ -37,6 +39,7 @@
"dev:wordpress:js": "NODE_ENV=development webpack-dev-server --config webpack.wordpress.config.js",
"dev:wordpress:css": "run-p dev:wordpress:css:*",
"dev:wordpress:css:main": "node-sass src/form.scss | postcss --config postcss.config.json -u autoprefixer -u postcss-custom-properties --no-map -o targets/wordpress/happychat.css",
"dev:wordpress:css:calypso": "node-sass src/ui/css/themes/_calypso.scss | postcss --config postcss.config.json -u autoprefixer -u postcss-custom-properties --no-map -o targets/wordpress/calypso.css",
"dev:wordpress:css:woo": "node-sass src/ui/css/themes/_woo.scss | postcss --config postcss.config.json -u autoprefixer -u postcss-custom-properties --no-map -o targets/wordpress/woo.css",
"dev:wordpress:css:jpop": "node-sass src/ui/css/themes/_jpop.scss | postcss --config postcss.config.json -u autoprefixer -u postcss-custom-properties --no-map -o targets/wordpress/jpop.css",

Expand All @@ -45,20 +48,23 @@
"build:standalone:js": "NODE_ENV=production webpack -p --config webpack.standalone.config.js -p",
"build:standalone:css": "run-p build:standalone:css:*",
"build:standalone:css:main": "node-sass src/form.scss --output-style compressed | postcss --config postcss.config.json -u autoprefixer -u postcss-custom-properties --no-map -o targets/standalone/happychat.css",
"build:standalone:css:calypso": "node-sass src/ui/css/themes/_calypso.scss --output-style compressed | postcss --config postcss.config.json -u autoprefixer -u postcss-custom-properties --no-map -o targets/standalone/calypso.css",
"build:standalone:css:woo": "node-sass src/ui/css/themes/_woo.scss --output-style compressed | postcss --config postcss.config.json -u autoprefixer -u postcss-custom-properties --no-map -o targets/standalone/woo.css",
"build:standalone:css:jpop": "node-sass src/ui/css/themes/_jpop.scss --output-style compressed | postcss --config postcss.config.json -u autoprefixer -u postcss-custom-properties --no-map -o targets/standalone/jpop.css",

"build:npm": "run-p build:npm:*",
"build:npm:js": "NODE_ENV=production ./node_modules/babel-cli/bin/babel.js src --out-dir targets/npm",
"build:npm:css": "run-p build:npm:css:*",
"build:npm:css:main": "node-sass src/form.scss --output-style compressed | postcss --config postcss.config.json -u autoprefixer -u postcss-custom-properties --no-map -o targets/npm/happychat.css",
"build:npm:css:calypso": "node-sass src/ui/css/themes/_calypso.scss --output-style compressed | postcss --config postcss.config.json -u autoprefixer -u postcss-custom-properties --no-map -o targets/npm/calypso.css",
"build:npm:css:woo": "node-sass src/ui/css/themes/_woo.scss --output-style compressed | postcss --config postcss.config.json -u autoprefixer -u postcss-custom-properties --no-map -o targets/npm/woo.css",
"build:npm:css:jpop": "node-sass src/ui/css/themes/_jpop.scss --output-style compressed | postcss --config postcss.config.json -u autoprefixer -u postcss-custom-properties --no-map -o targets/npm/jpop.css",

"build:wordpress": "run-p build:wordpress:*",
"build:wordpress:js": "NODE_ENV=production webpack -p --config webpack.wordpress.config.js",
"build:wordpress:css": "run-p build:wordpress:css:*",
"build:wordpress:css:main": "node-sass src/form.scss --output-style compressed | postcss --config postcss.config.json -u autoprefixer -u postcss-custom-properties --no-map -o targets/wordpress/assets/happychat.css",
"build:wordpress:css:calypso": "node-sass src/ui/css/themes/_calypso.scss --output-style compressed | postcss --config postcss.config.json -u autoprefixer -u postcss-custom-properties --no-map -o targets/wordpress/assets/calypso.css",
"build:wordpress:css:woo": "node-sass src/ui/css/themes/_woo.scss --output-style compressed | postcss --config postcss.config.json -u autoprefixer -u postcss-custom-properties --no-map -o targets/wordpress/assets/woo.css",
"build:wordpress:css:jpop": "node-sass src/ui/css/themes/_jpop.scss --output-style compressed | postcss --config postcss.config.json -u autoprefixer -u postcss-custom-properties --no-map -o targets/wordpress/assets/jpop.css",
"test": "jest -c jest.config.json"
Expand Down
6 changes: 4 additions & 2 deletions src/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
renderError,
} from './index';
import authenticator from 'src/lib/auth';
import { LAYOUT_MAX_WIDTH_FIXED_HEIGHT } from './constants';
import { LAYOUT_MAX_WIDTH_FIXED_HEIGHT, THEME_CALYPSO } from './constants';

const api = {
/**
Expand All @@ -35,6 +35,7 @@ const api = {
* @param {String} layout Optional. The chat layout max-width-fixed-height | max-parent-size | panel-fixed-size | panel-max-parent-size
* @param {string} nodeId Mandatory. HTML Node id where Happychat will be rendered.
* @param {Object} user Optional. Customer information .
* @param {string} theme Optional. Selected color theme.
*/
open: ( {
authentication,
Expand All @@ -45,10 +46,11 @@ const api = {
layout = LAYOUT_MAX_WIDTH_FIXED_HEIGHT,
nodeId,
user,
theme = THEME_CALYPSO,
} ) => {
authenticator.init( authentication );

const targetNode = createTargetNode( { entryOptions, groups, layout, nodeId } );
const targetNode = createTargetNode( { entryOptions, groups, layout, nodeId, theme } );

authenticator.login()
.then( () => isEmpty( user ) ? authenticator.getUser() : Promise.resolve( user ) )
Expand Down
5 changes: 5 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ export const LAYOUT_MAX_PARENT_SIZE = 'max-parent-size';
export const LAYOUT_PANEL_FIXED_SIZE = 'panel-fixed-size';
export const LAYOUT_PANEL_MAX_PARENT_SIZE = 'panel-max-parent-size';

// Themes
export const THEME_CALYPSO = 'calypso';
export const THEME_WOO = 'woo';
export const THEME_JPOP = 'jpop';

// Entry
export const ENTRY_CHAT = 'chat';
export const ENTRY_FORM = 'form';
1 change: 0 additions & 1 deletion src/form.scss
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
@import 'ui/css/shared/mixins/noticon';
@import 'ui/css/shared/animation';
@import 'ui/css/shared/classes';
@import 'ui/css/themes/main';

// General styles
@import 'ui/css/shared/vendor/noticon'; // .noticon
Expand Down
43 changes: 22 additions & 21 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
LAYOUT_MAX_PARENT_SIZE,
LAYOUT_PANEL_FIXED_SIZE,
LAYOUT_PANEL_MAX_PARENT_SIZE,
THEME_CALYPSO,
} from 'src/constants';

const store = createStore(
Expand All @@ -55,26 +56,26 @@ const dispatchAssetsFinishedDownloading = () => store.dispatch( setAssetsLoaded(
* @returns {HTMLNode} Target node where Happychat can hook into.
*/
const createIframe = ( props, assetsLoadedHook = () => {} ) => {
const { entryOptions, groups, layout, nodeId } = props;
const { entryOptions, groups, layout, nodeId, theme } = props;
const iframeElement = document.createElement( 'iframe' );

let iframeHeight = 0;
let iframeWidth = 0;
switch ( layout ) {
case LAYOUT_MAX_WIDTH_FIXED_HEIGHT:
const primaryHasAnySecondary = options =>
Array.isArray( options ) && find( options, opt => opt.secondaryOptions );
const primaryHasAnySecondary = options =>
Array.isArray( options ) && find( options, opt => opt.secondaryOptions );

const isThereAnySecondaryOptions = options =>
options &&
( options.secondaryOptions || primaryHasAnySecondary( entryOptions.primaryOptions ) );
const isThereAnySecondaryOptions = options =>
options &&
( options.secondaryOptions || primaryHasAnySecondary( entryOptions.primaryOptions ) );

// Calculate height based on the number of components
// the iframe may need to render.
// Calculate height based on the number of components
// the iframe may need to render.
iframeHeight = 480;
iframeHeight = iframeHeight + ( entryOptions && entryOptions.primaryOptions ? 110 : 0 );
iframeHeight = iframeHeight + ( isThereAnySecondaryOptions( entryOptions ) ? 110 : 0 );
iframeHeight = iframeHeight + ( entryOptions && entryOptions.itemList ? 70 : 0 );
iframeHeight = iframeHeight + ( entryOptions && entryOptions.primaryOptions ? 110 : 0 );
iframeHeight = iframeHeight + ( isThereAnySecondaryOptions( entryOptions ) ? 110 : 0 );
iframeHeight = iframeHeight + ( entryOptions && entryOptions.itemList ? 70 : 0 );

iframeHeight = iframeHeight + 'em';
iframeWidth = '100%';
Expand Down Expand Up @@ -157,20 +158,17 @@ const createIframe = ( props, assetsLoadedHook = () => {} ) => {
styleHC.setAttribute( 'type', 'text/css' );
styleHC.setAttribute( 'href', config( 'css_url' ) );

// TODO: rework this to use skills and have local themes loaded
const styleHCPromise = new Promise( resolve => ( styleHC.onload = () => resolve() ) );

const styleHCTheme = document.createElement( 'link' );
styleHCTheme.setAttribute( 'rel', 'stylesheet' );
styleHCTheme.setAttribute( 'type', 'text/css' );
let styleHCThemePromise = Promise.resolve();
if ( groups && groups.length > 0 ) {
const groupName = groups[ 0 ];
if ( groupName === 'woo' || groupName === 'jpop' ) {
styleHCTheme.setAttribute( 'href', 'https://widgets.wp.com/happychat/' + groupName + '.css' );
styleHCThemePromise = new Promise( resolve => ( styleHCTheme.onload = () => resolve() ) );
}
}

// if we are not using the default theme load the requested one
// TODO: cleanup the css url to use base url
styleHCTheme.setAttribute( 'href', config( 'css_url' ).replace( 'happychat.css', theme + '.css' ) );
styleHCThemePromise = new Promise( resolve => ( styleHCTheme.onload = () => resolve() ) );

Promise.all( [ styleNoticonPromise, styleHCPromise, styleHCThemePromise ] ).then( () =>
assetsLoadedHook()
Expand Down Expand Up @@ -222,12 +220,14 @@ export const renderHappychat = (
username,
display_name,
avatar_URL,
language,
localeSlug,
},
groups = [ HAPPYCHAT_GROUP_WPCOM ],
canChat = true,
entry = ENTRY_FORM,
entryOptions = {},
layout,
}
) => {
const { fallbackTicket } = entryOptions;
Expand All @@ -241,7 +241,8 @@ export const renderHappychat = (
} )
);
store.dispatch( setGroups( groups ) );
store.dispatch( setLocale( localeSlug ) );
// TODO: fix this - currentUser object differs from calypso to oauth.
store.dispatch( setLocale( language | localeSlug ) );
store.dispatch( setFallbackTicketOptions( fallbackTicket ) );

isAnyCanChatPropFalse( canChat, entryOptions )
Expand All @@ -250,7 +251,7 @@ export const renderHappychat = (

ReactDOM.render(
<Provider store={ store }>
<Happychat entry={ entry } entryOptions={ entryOptions } />
<Happychat entry={ entry } entryOptions={ entryOptions } layout={ layout } />
</Provider>,
targetNode
);
Expand Down
1 change: 1 addition & 0 deletions src/ui/css/_main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ body {
font-size: 15px;
line-height: 1.5;
color: var(--neutral-dark);
background: var(--neutral-lighten-30);
margin: 1; // separate from iframe, so children can style the borders
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
/** @format */

@import '../shared/colors';
@import '../shared/functions/tint-and-shade';

:root {
--selected: $blue-medium;
--selected-darken-5: darken($blue-medium, 5%);
Expand Down
1 change: 1 addition & 0 deletions targets/standalone/example.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
},
},
nodeId: 'support',
theme: 'jpop',
groups: ['woo'],
entryOptions: {
primaryOptions: [
Expand Down