• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Yoast / wordpress-seo / 93a59aae2ae295f52664351b071e54819677a514

28 Jan 2025 04:25PM UTC coverage: 52.624% (-2.0%) from 54.601%
93a59aae2ae295f52664351b071e54819677a514

Pull #21987

github

web-flow
Merge 70c38ae36 into 50c07b20a
Pull Request #21987: Export inclusive language csv contents

7747 of 13781 branches covered (56.22%)

Branch coverage included in aggregate %.

20447 of 39795 relevant lines covered (51.38%)

57816.76 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/packages/social-metadata-previews/src/editor/SocialPreviewEditor.js
1
/* External dependencies */
2
import { SimulatedLabel } from "@yoast/components";
3
import React, { Component } from "react";
4
import PropTypes from "prop-types";
5

6
/* Internal dependencies */
7
import { SocialMetadataPreviewForm } from "@yoast/social-metadata-forms";
8
import FacebookPreview from "../facebook/FacebookPreview";
9
import TwitterPreview from "../twitter/TwitterPreview";
10
import { recommendedReplacementVariablesShape, replacementVariablesShape } from "@yoast/replacement-variable-editor";
11

12
/**
13
 * A form with an image selection button, a title input field and a description field and the social preview.
14
 *
15
 * @returns {void} Void.
16
 */
17
class SocialPreviewEditor extends Component {
18
        /**
19
         * The constructor.
20
         * @param {Object} props The props object.
21
         *
22
         * @returns {void}
23
         */
24
        constructor( props ) {
25
                super( props );
×
26

27
                this.state = {
×
28
                        activeField: "",
29
                        hoveredField: "",
30
                };
31

32
                this.SocialPreview = props.socialMediumName === "Social" ? FacebookPreview : TwitterPreview;
×
33
                this.setHoveredField = this.setHoveredField.bind( this );
×
34
                this.setActiveField = this.setActiveField.bind( this );
×
35
                this.setEditorRef = this.setEditorRef.bind( this );
×
36
                this.setEditorFocus = this.setEditorFocus.bind( this );
×
37
        }
38

39
        /**
40
         * Sets the field that the mouse is hovering over in state.
41
         *
42
         * @param {string} field The field that is hovered over.
43
         *
44
         * @returns {void}
45
         */
46
        setHoveredField( field ) {
47
                if ( field === this.state.hoveredField ) {
×
48
                        return;
×
49
                }
50
                this.setState( {
×
51
                        hoveredField: field,
52
                } );
53
        }
54

55
        /**
56
         * Sets the active field that is selected in state.
57
         *
58
         * @param {string} field The field that is selected.
59
         *
60
         * @returns {void}
61
         */
62
        setActiveField( field ) {
63
                if ( field === this.state.activeField ) {
×
64
                        return;
×
65
                }
66
                this.setState(
×
67
                        { activeField: field },
68
                        () => this.setEditorFocus( field )
×
69
                );
70
        }
71

72
        /**
73
         * Sets focus on the editor that is the active field.
74
         *
75
         * @param {String} field The active field belonging to the editor to focus.
76
         *
77
         * @returns {void}
78
         */
79
        setEditorFocus( field ) {
80
                switch ( field ) {
×
81
                        case "title":
82
                                this.titleEditorRef.focus();
×
83
                                break;
×
84
                        case "description":
85
                                this.descriptionEditorRef.focus();
×
86
                                break;
×
87
                }
88
        }
89

90
        /**
91
         * Sets the reference of each editor.
92
         * Used by child components to communicate with this focus managing component.
93
         * This component can then call the .focus() function on the passed refs.
94
         *
95
         * @param {string} field The field belonging to the editor that belongs to the ref.
96
         * @param {*} ref A ref to an editor.
97
         *
98
         * @returns {void}
99
         */
100
        setEditorRef( field, ref ) {
101
                switch ( field ) {
×
102
                        case "title":
103
                                this.titleEditorRef = ref;
×
104
                                break;
×
105
                        case "description":
106
                                this.descriptionEditorRef = ref;
×
107
                                break;
×
108
                }
109
        }
110

111
        /**
112
         * The render function.
113
         *
114
         * @returns {void} Void.
115
         */
116
        render() {
117
                const {
118
                        onDescriptionChange,
119
                        onTitleChange,
120
                        onSelectImageClick,
121
                        onRemoveImageClick,
122
                        socialMediumName,
123
                        imageWarnings,
124
                        siteUrl,
125
                        description,
126
                        descriptionInputPlaceholder,
127
                        descriptionPreviewFallback,
128
                        imageUrl,
129
                        imageFallbackUrl,
130
                        alt,
131
                        title,
132
                        titleInputPlaceholder,
133
                        titlePreviewFallback,
134
                        replacementVariables,
135
                        recommendedReplacementVariables,
136
                        applyReplacementVariables,
137
                        onReplacementVariableSearchChange,
138
                        isPremium,
139
                        isLarge,
140
                        socialPreviewLabel,
141
                        idSuffix,
142
                        activeMetaTabId,
143
                } = this.props;
×
144

145
                // Set fallbacks if title and/or description are empty.
146
                const previewTitle = title || titlePreviewFallback;
×
147
                const previewDescription = description || descriptionPreviewFallback;
×
148

149
                const replacedVars = applyReplacementVariables( { title: previewTitle, description: previewDescription } );
×
150

151
                return (
×
152
                        <React.Fragment>
153
                                { socialPreviewLabel && <SimulatedLabel>
×
154
                                        { socialPreviewLabel }
155
                                </SimulatedLabel> }
156
                                <this.SocialPreview
157
                                        onMouseHover={ this.setHoveredField }
158
                                        onSelect={ this.setActiveField }
159
                                        onImageClick={ onSelectImageClick }
160
                                        siteUrl={ siteUrl }
161
                                        title={ replacedVars.title }
162
                                        description={ replacedVars.description }
163
                                        imageUrl={ imageUrl }
164
                                        imageFallbackUrl={ imageFallbackUrl }
165
                                        alt={ alt }
166
                                        isLarge={ isLarge }
167
                                        activeMetaTabId={ activeMetaTabId }
168
                                />
169
                                <SocialMetadataPreviewForm
170
                                        onDescriptionChange={ onDescriptionChange }
171
                                        socialMediumName={ socialMediumName }
172
                                        title={ title }
173
                                        titleInputPlaceholder={ titleInputPlaceholder }
174
                                        onRemoveImageClick={ onRemoveImageClick }
175
                                        imageSelected={ !! imageUrl }
176
                                        imageUrl={ imageUrl }
177
                                        imageFallbackUrl={ imageFallbackUrl }
178
                                        onTitleChange={ onTitleChange }
179
                                        onSelectImageClick={ onSelectImageClick }
180
                                        description={ description }
181
                                        descriptionInputPlaceholder={ descriptionInputPlaceholder }
182
                                        imageWarnings={ imageWarnings }
183
                                        replacementVariables={ replacementVariables }
184
                                        recommendedReplacementVariables={ recommendedReplacementVariables }
185
                                        onReplacementVariableSearchChange={ onReplacementVariableSearchChange }
186
                                        onMouseHover={ this.setHoveredField }
187
                                        hoveredField={ this.state.hoveredField }
188
                                        onSelect={ this.setActiveField }
189
                                        activeField={ this.state.activeField }
190
                                        isPremium={ isPremium }
191
                                        setEditorRef={ this.setEditorRef }
192
                                        idSuffix={ idSuffix }
193
                                />
194
                        </React.Fragment>
195
                );
196
        }
197
}
198

199
SocialPreviewEditor.propTypes = {
×
200
        title: PropTypes.string.isRequired,
201
        onTitleChange: PropTypes.func.isRequired,
202
        description: PropTypes.string.isRequired,
203
        onDescriptionChange: PropTypes.func.isRequired,
204
        imageUrl: PropTypes.string.isRequired,
205
        imageFallbackUrl: PropTypes.string.isRequired,
206
        onSelectImageClick: PropTypes.func.isRequired,
207
        onRemoveImageClick: PropTypes.func.isRequired,
208
        socialMediumName: PropTypes.string.isRequired,
209
        alt: PropTypes.string,
210
        isPremium: PropTypes.bool,
211
        imageWarnings: PropTypes.array,
212
        isLarge: PropTypes.bool,
213
        siteUrl: PropTypes.string,
214
        descriptionInputPlaceholder: PropTypes.string,
215
        titleInputPlaceholder: PropTypes.string,
216
        descriptionPreviewFallback: PropTypes.string,
217
        titlePreviewFallback: PropTypes.string,
218
        replacementVariables: replacementVariablesShape,
219
        recommendedReplacementVariables: recommendedReplacementVariablesShape,
220
        applyReplacementVariables: PropTypes.func,
221
        onReplacementVariableSearchChange: PropTypes.func,
222
        socialPreviewLabel: PropTypes.string,
223
        idSuffix: PropTypes.string,
224
        activeMetaTabId: PropTypes.string,
225
};
226

227
SocialPreviewEditor.defaultProps = {
×
228
        imageWarnings: [],
229
        recommendedReplacementVariables: [],
230
        replacementVariables: [],
231
        isPremium: false,
232
        isLarge: true,
233
        siteUrl: "",
234
        descriptionInputPlaceholder: "",
235
        titleInputPlaceholder: "",
236
        descriptionPreviewFallback: "",
237
        titlePreviewFallback: "",
238
        alt: "",
239
        applyReplacementVariables: data => data,
×
240
        onReplacementVariableSearchChange: null,
241
        socialPreviewLabel: "",
242
        idSuffix: "",
243
        activeMetaTabId: "",
244
};
245

246
export default SocialPreviewEditor;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc