mirror of
https://github.com/wassname/talk.git
synced 2026-07-08 14:40:52 +08:00
Merge branch 'master' into introspection-fix
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
.container {
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.copy {
|
||||
padding: 20px 0;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import React from 'react';
|
||||
import styles from './Forbidden.css';
|
||||
|
||||
const Forbidden = () => (
|
||||
<div className={styles.container}>
|
||||
<p className={styles.copy}>
|
||||
This page is for team use only. Please contact an administrator if you
|
||||
want to join this team.
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default Forbidden;
|
||||
@@ -1,4 +1,6 @@
|
||||
.layout {
|
||||
margin: 0 auto;
|
||||
background-color: #FAFAFA;
|
||||
}
|
||||
height: inherit;
|
||||
min-height: calc(100vh - 58px);
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import { logout } from 'coral-framework/actions/auth';
|
||||
import { can } from 'coral-framework/services/perms';
|
||||
import UserDetail from 'coral-admin/src/containers/UserDetail';
|
||||
import PropTypes from 'prop-types';
|
||||
import Forbidden from '../components/Forbidden';
|
||||
|
||||
class LayoutContainer extends React.Component {
|
||||
render() {
|
||||
@@ -47,10 +48,7 @@ class LayoutContainer extends React.Component {
|
||||
} else {
|
||||
return (
|
||||
<Layout {...this.props} handleLogout={logout}>
|
||||
<p>
|
||||
This page is for team use only. Please contact an administrator if
|
||||
you want to join this team.
|
||||
</p>
|
||||
<Forbidden />
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,10 +6,6 @@
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
:global(html) {
|
||||
height: inherit;
|
||||
}
|
||||
|
||||
.list {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
@@ -15,14 +15,13 @@ import QuestionBox from '../../../components/QuestionBox';
|
||||
import { Tab, TabCount, TabPane } from 'coral-ui';
|
||||
import cn from 'classnames';
|
||||
import get from 'lodash/get';
|
||||
|
||||
import { reverseCommentParentTree } from '../../../graphql/utils';
|
||||
import AllCommentsPane from './AllCommentsPane';
|
||||
import ExtendableTabPanel from '../../../containers/ExtendableTabPanel';
|
||||
import ChangedUsername from './ChangedUsername';
|
||||
import CommentNotFound from '../containers/CommentNotFound';
|
||||
|
||||
import styles from './Stream.css';
|
||||
import ChangedUsername from './ChangedUsername';
|
||||
|
||||
class Stream extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@@ -238,7 +237,11 @@ class Stream extends React.Component {
|
||||
keepCommentBox);
|
||||
|
||||
if (highlightedComment === null) {
|
||||
return <StreamError>{t('stream.comment_not_found')}</StreamError>;
|
||||
return (
|
||||
<StreamError>
|
||||
<CommentNotFound />
|
||||
</StreamError>
|
||||
);
|
||||
}
|
||||
|
||||
const slotPassthrough = { root, asset };
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button } from 'coral-ui';
|
||||
import { setActiveTab } from '../../../actions/embed';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
import t from 'coral-framework/services/i18n';
|
||||
|
||||
class CommentNotFound extends React.Component {
|
||||
showAllTab = () => {
|
||||
this.props.setActiveTab('all');
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<p>{t('stream.comment_not_found')}</p>
|
||||
<Button onClick={this.showAllTab}>Show all comments</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
CommentNotFound.propTypes = {
|
||||
setActiveTab: PropTypes.func,
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch =>
|
||||
bindActionCreators(
|
||||
{
|
||||
setActiveTab,
|
||||
},
|
||||
dispatch
|
||||
);
|
||||
|
||||
export default connect(null, mapDispatchToProps)(CommentNotFound);
|
||||
+10
-10
@@ -136,16 +136,6 @@ sidebar:
|
||||
url: /plugins-directory/
|
||||
- title: Plugin Recipes
|
||||
url: /plugin-recipes/
|
||||
- title: Slots and Plugins
|
||||
url: /slots-and-plugins/
|
||||
- title: Tutorials
|
||||
children:
|
||||
- title: Creating a Basic Plugin
|
||||
url: /building-basic-plugin/
|
||||
- title: Customizing Plugins with Coral UI
|
||||
url: /customizing-plugins-coral-ui/
|
||||
- title: When You've Installed Talk
|
||||
url: /when-youve-installed-talk/
|
||||
- title: API
|
||||
children:
|
||||
- title: GraphQL Overview
|
||||
@@ -154,6 +144,16 @@ sidebar:
|
||||
url: /api/graphql/
|
||||
- title: Server Plugin API
|
||||
url: /api/server/
|
||||
- title: Client Plugin API
|
||||
url: /api/client/
|
||||
- title: Plugin Slots API
|
||||
url: /api/slots/
|
||||
- title: Tutorials
|
||||
children:
|
||||
- title: Creating a Basic Plugin
|
||||
url: /building-basic-plugin/
|
||||
- title: Customizing Plugins with Coral UI
|
||||
url: /customizing-plugins-coral-ui/
|
||||
- title: Migrating
|
||||
children:
|
||||
- title: Migrating to v4.0.0
|
||||
|
||||
@@ -140,5 +140,3 @@ For the first month or so, we recommend including a link to the launch article m
|
||||
A regular space for conversation about the conversation is always welcome in any successful community, and is a great source of ideas for improvement.
|
||||
|
||||
**_We hope you enjoy using Talk, and that it helps your communities to thrive. If you have any questions or suggestions for this piece, or would like to try Talk on your site, please [contact us.](https://coralproject.net/contact.html)_**
|
||||
|
||||
[_Red button image by włodi_](https://www.flickr.com/photos/wlodi/3085157011/)_, CC-BY-SA 2.0_
|
||||
|
||||
@@ -0,0 +1,301 @@
|
||||
---
|
||||
title: Client Plugin API
|
||||
permalink: /api/client/
|
||||
toc: true
|
||||
class: configuration
|
||||
---
|
||||
|
||||
We created a set of utilities to make it easier to create and add functionality to plugins.
|
||||
Feel free to check all the utilities here: `talk/plugin-api`.
|
||||
|
||||
## Actions
|
||||
#### Admin
|
||||
* `viewUserDetail`
|
||||
|
||||
#### Auth
|
||||
* `setAuthToken`
|
||||
* `handleSuccessfulLogin`
|
||||
* `logout`
|
||||
|
||||
#### Notification
|
||||
* `notify`
|
||||
|
||||
#### Stream
|
||||
* `setSort`
|
||||
* `showSignInDialog``
|
||||
|
||||
### Import
|
||||
```
|
||||
import {notify} 'plugin-api/beta/actions';
|
||||
```
|
||||
|
||||
### Usage
|
||||
```js
|
||||
// Trigger a notification
|
||||
notify('success', t('suspenduser.notify_suspend_until', username, timeago(until))
|
||||
|
||||
// mapDispatchToProps
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
...bindActionCreators(
|
||||
{
|
||||
notify,
|
||||
},
|
||||
dispatch
|
||||
),
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Components
|
||||
* `Slot`
|
||||
You probably won’t need to use the `<Slot/>` component in your plugin. But there’s a chance you might want to add a Slot so another plugin gets injected in your plugin.
|
||||
|
||||
### Props
|
||||
* `fill ` : <String | Array> Name of the slot
|
||||
* `defaultComponent` : <Element | Array> The default component if no plugin component is provided to the Slot
|
||||
* `size` : <Number | Array> - How many components this Slot should show - Slot size or an Array of slot size
|
||||
* `passthrough`: <Object> - The properties that you want to pass to the Slot, therefore to the plugins.
|
||||
* `className` : <String> - Slot’s class name
|
||||
|
||||
### Import
|
||||
```
|
||||
import {Slot} 'plugin-api/beta/components';
|
||||
```
|
||||
|
||||
### Usage
|
||||
```js
|
||||
const slotPassthrough = {
|
||||
clearHeightCache,
|
||||
root,
|
||||
asset,
|
||||
comment,
|
||||
};
|
||||
|
||||
<Slot
|
||||
fill="adminCommentContent"
|
||||
className={className}
|
||||
defaultComponent={CommentFormatter}
|
||||
size={1}
|
||||
passthrough={slotPassthrough}
|
||||
/>
|
||||
```
|
||||
|
||||
* `IfSlotIsEmpty`
|
||||
|
||||
### Import
|
||||
```
|
||||
import {IfSlotIsEmpty} 'plugin-api/beta/components';
|
||||
```
|
||||
|
||||
### Usage
|
||||
```js
|
||||
<IfSlotIsEmpty
|
||||
slot="adminCommentContent"
|
||||
passthrough={slotPassthrough}
|
||||
/>
|
||||
```
|
||||
|
||||
* `IfSlotIsNotEmpty`
|
||||
|
||||
### Import
|
||||
```
|
||||
import {IfSlotIsNotEmpty} 'plugin-api/beta/components';
|
||||
```
|
||||
|
||||
### Usage
|
||||
```js
|
||||
<IfSlotIsNotEmpty
|
||||
slot="adminCommentContent"
|
||||
passthrough={slotPassthrough}
|
||||
/>
|
||||
```
|
||||
|
||||
* `ClickOutside`
|
||||
This utility handle click events outside the component.
|
||||
|
||||
### Props
|
||||
* `onClickOutside` : Takes handler function
|
||||
|
||||
#### Import
|
||||
```js
|
||||
import { ClickOutside } from 'plugin-api/beta/client/components';
|
||||
```
|
||||
|
||||
#### Usage
|
||||
```js
|
||||
<ClickOutside onClickOutside={this.handleClickOutside}>
|
||||
// Your component
|
||||
</ClickOutside>
|
||||
```
|
||||
|
||||
* `CommentAuthorName`
|
||||
* `CommentTimestamp`
|
||||
* `CommentDetail`
|
||||
* `CommentContent`
|
||||
* `ConfigureCard`
|
||||
* `StreamConfiguration`
|
||||
* `Recaptcha`
|
||||
|
||||
## HOCS - Higher Order Components
|
||||
*`withGraphQLExtension`*
|
||||
|
||||
This HOC allows components to register GraphQLExtensions for the framework. IMPORTANT: The extensions are only picked up when the component is used in a slot.
|
||||
|
||||
### Import
|
||||
```js
|
||||
import { withGraphQLExtension } from 'plugin-api/beta/hoc';
|
||||
```
|
||||
|
||||
### Usage
|
||||
```js
|
||||
withGraphQLExtension({
|
||||
mutations: {
|
||||
UpdateNotificationSettings: () => ({
|
||||
update: proxy => {...}
|
||||
})
|
||||
},
|
||||
fragments: {...},
|
||||
query: {...},
|
||||
})(MyComponent);
|
||||
```
|
||||
|
||||
And then update your `my-plugin/client/index.js`
|
||||
|
||||
```js
|
||||
export default {
|
||||
mySlot: [MyComponent],
|
||||
}
|
||||
```
|
||||
|
||||
* `withReaction`
|
||||
Provides you utilities to create components that interact with Reactions.
|
||||
|
||||
Check this tutorial to know more about the usage of `withReaction` [Creating a Basic Pride Reaction Plugin | Talk Documentation](https://docs.coralproject.net/talk/building-basic-plugin/)
|
||||
|
||||
### Import
|
||||
```js
|
||||
import { withReaction } from 'plugin-api/beta/hoc';
|
||||
```
|
||||
|
||||
### Usage
|
||||
```js
|
||||
export default withReaction('pride')(PrideButton);
|
||||
```
|
||||
|
||||
|
||||
* `withTags`
|
||||
Provides you utilities to create components that interact with Tags.
|
||||
|
||||
### Import
|
||||
```js
|
||||
import { withTags } from 'plugin-api/beta/hoc';
|
||||
```
|
||||
|
||||
### Usage
|
||||
```js
|
||||
export default withTags('featured')(FeaturedButton);
|
||||
```
|
||||
|
||||
|
||||
* `withSortOption`
|
||||
* `withEmit`
|
||||
* `excludeIf`
|
||||
* `withFragments`
|
||||
* `withMutation`
|
||||
* `withForgotPassword`
|
||||
* `withSignIn`
|
||||
* `withSignUp`
|
||||
* `withResendEmailConfirmation`
|
||||
* `withSetUsername`
|
||||
* `withEnumValues`
|
||||
* `withVariables`
|
||||
* `withFetchMore`
|
||||
* `withSubscribeToMore`
|
||||
* `withRefetch`
|
||||
* `withIgnoreUser`
|
||||
* `withBanUser`
|
||||
* `withUnbanUser`
|
||||
* `withStopIgnoringUser`
|
||||
* `withSetCommentStatus`
|
||||
* `compose`
|
||||
|
||||
## Services
|
||||
|
||||
* `t`
|
||||
To manage translations.
|
||||
|
||||
### Import
|
||||
```js
|
||||
import { t } from 'coral-framework/services/perms';
|
||||
```
|
||||
|
||||
* `timeago`
|
||||
Handle time with [timeago](https://github.com/hustcc/timeago.js)
|
||||
|
||||
### Import
|
||||
```js
|
||||
import { timeago } from 'coral-framework/services/perms';
|
||||
```
|
||||
|
||||
* `can`
|
||||
A permissions utility.
|
||||
|
||||
### Import
|
||||
```js
|
||||
import { can } from 'coral-framework/services/perms';
|
||||
```
|
||||
|
||||
### Usage
|
||||
```js
|
||||
{can(currentUser, 'UPDATE_CONFIG') && (
|
||||
<Link
|
||||
className={cn('talk-admin-nav-configure', styles.navLink)}
|
||||
to="/admin/configure"
|
||||
activeClassName={styles.active}
|
||||
>
|
||||
{t('configure.configure')}
|
||||
</Link>
|
||||
)}
|
||||
```
|
||||
|
||||
## Coral UI
|
||||
Coral UI is a set of components to help you build your UI. This powers our core.
|
||||
|
||||
### Import
|
||||
```js
|
||||
import {Button} 'plugin-api/beta/components/ui';
|
||||
```
|
||||
|
||||
### Components
|
||||
* `Alert`
|
||||
* `Dialog`
|
||||
* `CoralLogo`
|
||||
* `FabButton`
|
||||
* `TabBar`
|
||||
* `Tab`
|
||||
* `TabCount`
|
||||
* `TabContent`
|
||||
* `TabPane`
|
||||
* `Button`
|
||||
* `Spinner`
|
||||
* `Tooltip`
|
||||
* `PopupMenu`
|
||||
* `Checkbox`
|
||||
* `Icon`
|
||||
* `List`
|
||||
* `Item`
|
||||
* `Card`
|
||||
* `TextField`
|
||||
* `Success`
|
||||
* `Paginate`
|
||||
* `Wizard`
|
||||
* `WizardNav`
|
||||
* `SnackBar`
|
||||
* `TextArea`
|
||||
* `Drawer`
|
||||
* `Label`
|
||||
* `FlagLabel`
|
||||
* `Dropdown`
|
||||
* `Option`
|
||||
* `BareButton`
|
||||
@@ -377,7 +377,11 @@ en:
|
||||
|
||||
Which overrides the copy for the `embedlink.copy` template. You can
|
||||
also provide other languages as well by using the correct language
|
||||
prefix.
|
||||
prefix.
|
||||
|
||||
When creating a plugin using this `translations` hook to override copy
|
||||
from another plugin, be sure to list it after the plugin it's overriding
|
||||
in the `plugins.json` file.
|
||||
|
||||
### websockets
|
||||
|
||||
@@ -524,4 +528,4 @@ module.exports = {
|
||||
}
|
||||
};
|
||||
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
---
|
||||
title: Slots and Plugins
|
||||
permalink: /slots-and-plugins/
|
||||
title: Plugin Slots API
|
||||
permalink: /api/slots/
|
||||
toc: true
|
||||
class: configuration
|
||||
---
|
||||
|
||||
Plugins make use of **"slots"** in order to change Talk's interface.
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "talk",
|
||||
"version": "4.2.2",
|
||||
"version": "4.3.0",
|
||||
"description": "A better commenting experience from Mozilla, The New York Times, and the Washington Post. https://coralproject.net",
|
||||
"main": "app.js",
|
||||
"private": true,
|
||||
|
||||
+2
-11
@@ -4,17 +4,8 @@
|
||||
<meta name="viewport" content="initial-scale=1, maximum-scale=1">
|
||||
<title>Talk - Coral Admin</title>
|
||||
<style media="screen">
|
||||
body, #root {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
background-color: #FAFAFA;
|
||||
font-family: 'Roboto', sans-serif;
|
||||
}
|
||||
|
||||
#root > div {
|
||||
height: 100%;
|
||||
}
|
||||
html, body, #root, #root > div { min-height: 100%; }
|
||||
body { margin: 0; background-color: #FAFAFA; font-family: 'Roboto', sans-serif; }
|
||||
</style>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://code.getmdl.io/1.2.1/material.min.css">
|
||||
|
||||
Reference in New Issue
Block a user