Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Block: Chat #1632

Closed
wants to merge 7 commits into from
Closed
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
48 changes: 48 additions & 0 deletions blocks/library/chat/block.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
.wp-block-chat {
font-family: $editor-html-font;

> p {
margin: 0;

&:first-child .chat-author {
margin-top: 0;
}
}

.chat-author {
display: block;
margin-top: 1em;
color: $blue-wordpress;
}

.chat-message {
margin-left: 1em;
}

&.is-compact {
.chat-author {
display: inline;
margin: 0 .5em 0 0;
}

.chat-message {
margin-left: 0;
}
}

.chat-author-1 .chat-author {
color: $alert-yellow;
}

.chat-author-2 .chat-author {
color: $alert-red;
}

.chat-author-3 .chat-author {
color: $alert-green;
}

.chat-author-4 .chat-author {
color: $dark-gray-800;
}
}
69 changes: 69 additions & 0 deletions blocks/library/chat/chat-transcript.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* External dependencies
*/
import { uniq } from 'lodash';

/**
* WordPress dependencies
*/
import classnames from 'classnames';

export function normalizeTranscript( value ) {
const transcript = {
authors: [],
messages: [],
};

if ( ! value ) {
return transcript;
}

let authorIndex = -1;

value.split( '\n' ).map( ( line ) => {
line = line.trim();

const messageParts = line.split( ':' );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should add a limit param, so like line.split( ':', 2 ). Otherwise it will choke on a line like:

John: I really like the ratio 1:1.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then the message = messageParts.join( ':' ).trim() part below can be replaced with:

message = messageParts.shift().trim()

let message;

if ( 1 === messageParts.length ) {
message = messageParts.shift();
} else {
const author = messageParts.shift().trim();
message = messageParts.join( ':' ).trim();

transcript.authors.push( author );
transcript.authors = uniq( transcript.authors );
authorIndex = transcript.authors.indexOf( author );
}

transcript.messages.push( {
message: message,
authorIndex: authorIndex,
} );
} );

return transcript;
}

export default function ChatTranscript( { value, compact, className } ) {
// Normalize data
const transcript = normalizeTranscript( value );

const classes = classnames( className, { 'is-compact': compact } );

return (
<div className={ classes }>
{value && transcript.messages.map( ( entry, index ) => {
const author = -1 !== entry.authorIndex ? transcript.authors[ entry.authorIndex ] : undefined;

return (
entry.message && <p className={ author && `chat-author-${ entry.authorIndex }` } key={ index }>
{ author && <span className="chat-author">{ `${ author }:` }</span> }
<span className="chat-message">{ entry.message }</span>
</p>
);
} ) }
</div>
);
}
83 changes: 83 additions & 0 deletions blocks/library/chat/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/**
* External dependencies
*/
import TextareaAutosize from 'react-autosize-textarea';

/**
* WordPress dependencies
*/
import { Placeholder } from 'components';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note with #2172, these need to be updated to prefix the dependencies with @wordpress/. You will need to perform a rebase against the latest version of master and apply your changes:

git fetch origin
git rebase origin/master

import { __ } from 'i18n';

/**
* Internal dependencies
*/
import './block.scss';
import './style.scss';
import { registerBlockType, query } from '../../api';
import InspectorControls from '../../inspector-controls';
import ToggleControl from '../../inspector-controls/toggle-control';
import ChatTranscript from './chat-transcript';

const { html } = query;

registerBlockType( 'core/chat', {
title: __( 'Chat' ),

icon: 'format-chat',

category: 'formatting',

attributes: {
content: html(),
},

defaultAttributes: {
compact: false,
},

edit( { attributes, setAttributes, focus, setFocus, className } ) {
const { compact, content } = attributes;

const toggleCompact = () => setAttributes( { compact: ! compact } );

return [
focus && (
<InspectorControls key="inspector">
<ToggleControl
label={ __( 'Compact display' ) }
checked={ !! compact }
onChange={ toggleCompact }
/>
</InspectorControls>
),
focus && (
<Placeholder
key="placeholder"
icon="format-chat"
label={ __( 'Chat Transcript' ) }
className={ className }>
<TextareaAutosize
value={ content }
onFocus={ setFocus }
onChange={ ( event ) => setAttributes( { content: event.target.value } ) }
placeholder={ __( 'Paste transcript here…' ) }
/>
</Placeholder>
),
! focus && (
<ChatTranscript
className={ className }
value={ content }
compact={ compact }
/>
),
];
},

save( { attributes } ) {
const { compact, content } = attributes;

return <ChatTranscript value={ content } compact={ compact } />;
},
} );
20 changes: 20 additions & 0 deletions blocks/library/chat/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.wp-block-chat {
.components-placeholder__fieldset {
max-width: none;
}

textarea {
box-shadow: none;
background: $white;
font-family: $editor-html-font;
font-size: $text-editor-font-size;
color: $dark-gray-800;
border: 1px solid $light-gray-500;
border-radius: 4px;
margin: 0;
overflow-x: auto;
width: 100%;
min-height: 10em;
text-align: left;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we create a block.scss for frontend styling too, and extract the common styles applied for the editor and for frontend into the block.scss file?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There already is such a file or am I missing something?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each block should create its own block.scss (which are extracted and loaded in frontend too). See #1590 (we did this for other blocks)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's why blocks/library/chat/block.scss exists. What else is needed?

1 change: 1 addition & 0 deletions blocks/library/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ import './html';
import './freeform';
import './latest-posts';
import './cover-image';
import './chat';
13 changes: 13 additions & 0 deletions blocks/test/fixtures/core__chat.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- wp:core/chat {"compact":false} -->
Pascal: Alexa, open the window
Alexa: I'm not quite sure how to help you with
Pascal: Siri, tell me a joke
Siri: Pascal, get Siri-ous. Ha ha!
Pascal: OK, Google. Now it's your turn!
Google Home: Alexa, tell Siri to tell Pascal a better joke.
Pascal: Ugh!
Okay, that's enough. No internet for you anymore!
Alexa: 💔
Google Home: 😔
Siri: 📴
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's a problem here unless I'm missing something.

If I understand the code, this value will be parsed and reserialized differently (using HTML ...).
What happens if I try to re-edit the block again? The parser will fail?
Anyway, The source value and the serialized value should be the same (aside some spacing differences maybe) which makes me think we should store the raw value in the comment.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's a problem I still need to address, see #1632 (comment).

You can edit the block, but you will see all the HTML markup in the textarea.

I would love to store only the raw value, but then how can it be rendered on the front end?

Feedback last week was that it should be stored with (as little as possible) markup in the database and then we'll see from there.

Copy link
Contributor

@youknowriad youknowriad Jul 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok Maybe instead of storing the value in its currenf format, we should extract a more "normalized" value, something like:

content: query( 'p', {
  authorId: attr( 'class' ),
  author: html( '.chat-author' ),
  message: hmlt( '.chat-message' ),
} )

which I think should return something like:

const content = [
  { authorId, author, message }
];

And when typing in the text area, parsing the textarea value to the format above before calling the setAttributes

<!-- /wp:core/chat -->
10 changes: 10 additions & 0 deletions blocks/test/fixtures/core__chat.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[
{
"uid": "_uid_0",
"name": "core/chat",
"attributes": {
"compact": false,
"content": "Pascal: Alexa, open the window\nAlexa: I'm not quite sure how to help you with\nPascal: Siri, tell me a joke\nSiri: Pascal, get Siri-ous. Ha ha!\nPascal: OK, Google. Now it's your turn!\nGoogle Home: Alexa, tell Siri to tell Pascal a better joke.\nPascal: Ugh!\nOkay, that's enough. No internet for you anymore!\nAlexa: 💔\nGoogle Home: 😔\nSiri: 📴"
}
}
]
13 changes: 13 additions & 0 deletions blocks/test/fixtures/core__chat.parsed.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[
{
"blockName": "core/chat",
"attrs": {
"compact": false
},
"rawContent": "\nPascal: Alexa, open the window\nAlexa: I'm not quite sure how to help you with\nPascal: Siri, tell me a joke\nSiri: Pascal, get Siri-ous. Ha ha!\nPascal: OK, Google. Now it's your turn!\nGoogle Home: Alexa, tell Siri to tell Pascal a better joke.\nPascal: Ugh!\nOkay, that's enough. No internet for you anymore!\nAlexa: 💔\nGoogle Home: 😔\nSiri: 📴\n"
},
{
"attrs": {},
"rawContent": "\n"
}
]
15 changes: 15 additions & 0 deletions blocks/test/fixtures/core__chat.serialized.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!-- wp:core/chat {"compact":false} -->
<div class="wp-block-chat">
<p class="chat-author-1"><span class="chat-author"> Pascal: </span><span class="chat-message">Alexa, open the window</span></p>
<p class="chat-author-2"><span class="chat-author"> Alexa: </span><span class="chat-message">I&#x27;m not quite sure how to help you with</span></p>
<p class="chat-author-1"><span class="chat-author"> Pascal: </span><span class="chat-message">Siri, tell me a joke</span></p>
<p class="chat-author-3"><span class="chat-author"> Siri: </span><span class="chat-message">Pascal, get Siri-ous. Ha ha!</span></p>
<p class="chat-author-1"><span class="chat-author"> Pascal: </span><span class="chat-message">OK, Google. Now it&#x27;s your turn!</span></p>
<p class="chat-author-4"><span class="chat-author"> Google Home: </span><span class="chat-message">Alexa, tell Siri to tell Pascal a better joke.</span></p>
<p class="chat-author-1"><span class="chat-author"> Pascal: </span><span class="chat-message">Ugh!</span></p>
<p class="chat-author-1"><span class="chat-message">Okay, that&#x27;s enough. No internet for you anymore!</span></p>
<p class="chat-author-2"><span class="chat-author"> Alexa: </span><span class="chat-message">💔</span></p>
<p class="chat-author-4"><span class="chat-author"> Google Home: </span><span class="chat-message">😔</span></p>
<p class="chat-author-3"><span class="chat-author"> Siri: </span><span class="chat-message">📴</span></p>
</div>
<!-- /wp:core/chat -->