mirror of
https://github.com/wassname/talk.git
synced 2026-07-16 11:22:16 +08:00
Merge branch 'master' into fix-my-profile-title-link
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
:global {
|
||||
html, body, #root, #root > div {
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
background-color: #FAFAFA;
|
||||
font-family: 'Roboto', sans-serif;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import ToastContainer from './ToastContainer';
|
||||
import './App.css';
|
||||
import 'material-design-lite';
|
||||
|
||||
import AppRouter from '../AppRouter';
|
||||
|
||||
@@ -37,7 +37,8 @@ export default class Popup extends Component {
|
||||
this.onBlur();
|
||||
};
|
||||
|
||||
// Use `onunload` instead of `onbeforeunload` which is not supported in IOS Safari.
|
||||
// Use `onunload` instead of `onbeforeunload` which is not supported in iOS
|
||||
// Safari.
|
||||
this.ref.onunload = () => {
|
||||
this.onUnload();
|
||||
|
||||
@@ -46,10 +47,15 @@ export default class Popup extends Component {
|
||||
}
|
||||
|
||||
this.resetCallbackInterval = setInterval(() => {
|
||||
if (this.ref && this.ref.onload === null) {
|
||||
clearInterval(this.resetCallbackInterval);
|
||||
this.resetCallbackInterval = null;
|
||||
this.setCallbacks();
|
||||
try {
|
||||
if (this.ref && this.ref.onload === null) {
|
||||
clearInterval(this.resetCallbackInterval);
|
||||
this.resetCallbackInterval = null;
|
||||
this.setCallbacks();
|
||||
}
|
||||
} catch (err) {
|
||||
// We could be getting a security exception here if the login page
|
||||
// gets redirected to another domain to authenticate.
|
||||
}
|
||||
}, 50);
|
||||
|
||||
|
||||
@@ -94,9 +94,13 @@ const createResolveFactory = (() => {
|
||||
|
||||
module.exports = async (req, res, next) => {
|
||||
try {
|
||||
// Attach the custom css url.
|
||||
const { customCssUrl } = await SettingsService.select('customCssUrl');
|
||||
// Attach the custom css url and organization name.
|
||||
const { customCssUrl, organizationName } = await SettingsService.select(
|
||||
'customCssUrl',
|
||||
'organizationName'
|
||||
);
|
||||
res.locals.customCssUrl = customCssUrl;
|
||||
res.locals.organizationName = organizationName;
|
||||
} catch (err) {
|
||||
console.warn(err);
|
||||
}
|
||||
|
||||
@@ -219,6 +219,7 @@
|
||||
"babel-plugin-dynamic-import-node": "^1.1.0",
|
||||
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
|
||||
"browserstack-local": "^1.3.0",
|
||||
"casual": "^1.5.19",
|
||||
"chai": "^3.5.0",
|
||||
"chai-as-promised": "^6.0.0",
|
||||
"chai-datetime": "^1.5.0",
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import * as actions from './constants';
|
||||
|
||||
export const startAttach = () => ({
|
||||
type: actions.START_ATTACH,
|
||||
});
|
||||
|
||||
export const finishAttach = () => ({
|
||||
type: actions.FINISH_ATTACH,
|
||||
});
|
||||
@@ -45,6 +45,10 @@ class AddEmailAddressDialog extends React.Component {
|
||||
),
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.props.startAttach();
|
||||
}
|
||||
|
||||
onChange = e => {
|
||||
const { name, value } = e.target;
|
||||
this.setState(
|
||||
@@ -99,7 +103,13 @@ class AddEmailAddressDialog extends React.Component {
|
||||
});
|
||||
};
|
||||
|
||||
confirmChanges = async () => {
|
||||
finish = () => {
|
||||
this.props.finishAttach();
|
||||
};
|
||||
|
||||
confirmChanges = async e => {
|
||||
e.preventDefault();
|
||||
|
||||
if (!this.validate()) {
|
||||
this.showErrors();
|
||||
return;
|
||||
@@ -113,7 +123,11 @@ class AddEmailAddressDialog extends React.Component {
|
||||
email: emailAddress,
|
||||
password: confirmPassword,
|
||||
});
|
||||
this.props.notify('success', 'Email Added!');
|
||||
|
||||
this.props.notify(
|
||||
'success',
|
||||
t('talk-plugin-local-auth.add_email.added.alert')
|
||||
);
|
||||
this.goToNextStep();
|
||||
} catch (err) {
|
||||
this.props.notify('error', getErrorMessages(err));
|
||||
@@ -143,13 +157,13 @@ class AddEmailAddressDialog extends React.Component {
|
||||
)}
|
||||
{step === 1 &&
|
||||
!settings.requireEmailConfirmation && (
|
||||
<EmailAddressAdded done={() => {}} />
|
||||
<EmailAddressAdded done={this.finish} />
|
||||
)}
|
||||
{step === 1 &&
|
||||
settings.requireEmailConfirmation && (
|
||||
<VerifyEmailAddress
|
||||
emailAddress={formData.emailAddress}
|
||||
done={() => {}}
|
||||
done={this.finish}
|
||||
/>
|
||||
)}
|
||||
</Dialog>
|
||||
@@ -161,6 +175,8 @@ AddEmailAddressDialog.propTypes = {
|
||||
attachLocalAuth: PropTypes.func.isRequired,
|
||||
notify: PropTypes.func.isRequired,
|
||||
root: PropTypes.object.isRequired,
|
||||
startAttach: PropTypes.func.isRequired,
|
||||
finishAttach: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default AddEmailAddressDialog;
|
||||
|
||||
@@ -41,7 +41,7 @@ const AddEmailContent = ({
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<form autoComplete="off">
|
||||
<form autoComplete="off" onSubmit={confirmChanges}>
|
||||
<InputField
|
||||
id="emailAddress"
|
||||
label={t('talk-plugin-local-auth.add_email.enter_email_address')}
|
||||
@@ -82,12 +82,9 @@ const AddEmailContent = ({
|
||||
showSuccess={false}
|
||||
/>
|
||||
<div className={styles.actions}>
|
||||
<a
|
||||
className={cn(styles.button, styles.proceed)}
|
||||
onClick={confirmChanges}
|
||||
>
|
||||
<button className={cn(styles.button, styles.proceed)}>
|
||||
{t('talk-plugin-local-auth.add_email.add_email_address')}
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
const prefix = 'TALK_LOCAL_AUTH';
|
||||
|
||||
export const START_ATTACH = `${prefix}_START_ATTACH`;
|
||||
export const FINISH_ATTACH = `${prefix}_FINISH_ATTACH`;
|
||||
@@ -3,10 +3,16 @@ import { bindActionCreators } from 'redux';
|
||||
import { connect, withFragments, excludeIf } from 'plugin-api/beta/client/hocs';
|
||||
import AddEmailAddressDialog from '../components/AddEmailAddressDialog';
|
||||
import { notify } from 'coral-framework/actions/notification';
|
||||
|
||||
import { withAttachLocalAuth } from '../hocs';
|
||||
import { startAttach, finishAttach } from '../actions';
|
||||
import get from 'lodash/get';
|
||||
|
||||
const mapDispatchToProps = dispatch => bindActionCreators({ notify }, dispatch);
|
||||
const mapStateToProps = ({ talkPluginLocalAuth: state }) => ({
|
||||
inProgress: state.inProgress,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch =>
|
||||
bindActionCreators({ notify, startAttach, finishAttach }, dispatch);
|
||||
|
||||
const withData = withFragments({
|
||||
root: gql`
|
||||
@@ -14,6 +20,13 @@ const withData = withFragments({
|
||||
me {
|
||||
id
|
||||
email
|
||||
state {
|
||||
status {
|
||||
username {
|
||||
status
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
settings {
|
||||
requireEmailConfirmation
|
||||
@@ -23,8 +36,13 @@ const withData = withFragments({
|
||||
});
|
||||
|
||||
export default compose(
|
||||
connect(null, mapDispatchToProps),
|
||||
connect(mapStateToProps, mapDispatchToProps),
|
||||
withAttachLocalAuth,
|
||||
withData,
|
||||
excludeIf(({ root: { me } }) => !me || me.email)
|
||||
excludeIf(
|
||||
({ root: { me }, inProgress }) =>
|
||||
!me ||
|
||||
get(me, 'state.status.username.status') === 'UNSET' ||
|
||||
(me.email && !inProgress)
|
||||
)
|
||||
)(AddEmailAddressDialog);
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import ChangePassword from './containers/ChangePassword';
|
||||
import AddEmailAddressDialog from './containers/AddEmailAddressDialog';
|
||||
import Profile from './containers/Profile';
|
||||
import translations from './translations.yml';
|
||||
import translations from '../translations.yml';
|
||||
import graphql from './graphql';
|
||||
import reducer from './reducer';
|
||||
|
||||
export default {
|
||||
reducer,
|
||||
translations,
|
||||
slots: {
|
||||
profileHeader: [Profile],
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import * as actions from './constants';
|
||||
|
||||
const initialState = {
|
||||
inProgress: false,
|
||||
};
|
||||
|
||||
export default function reducer(state = initialState, action) {
|
||||
switch (action.type) {
|
||||
case actions.START_ATTACH:
|
||||
return {
|
||||
inProgress: true,
|
||||
};
|
||||
case actions.FINISH_ATTACH:
|
||||
return {
|
||||
inProgress: false,
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ const mutators = require('./server/mutators');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
translations: path.join(__dirname, 'server', 'translations.yml'),
|
||||
translations: path.join(__dirname, 'translations.yml'),
|
||||
typeDefs,
|
||||
mutators,
|
||||
resolvers,
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
en:
|
||||
email:
|
||||
email_change_original:
|
||||
subject: Email change
|
||||
body: Your email address has been changed from {0} to {1}. If you did not initiate this change, please contact {2}. # TODO: update translation
|
||||
error:
|
||||
NO_LOCAL_PROFILE: No existing email address is associated with this account.
|
||||
LOCAL_PROFILE: An email address is already associated with this account.
|
||||
INCORRECT_PASSWORD: Provided password was incorrect.
|
||||
+10
-1
@@ -1,4 +1,12 @@
|
||||
en:
|
||||
email:
|
||||
email_change_original:
|
||||
subject: Email change
|
||||
body: Your email address has been changed from {0} to {1}. If you did not request this change, please contact {2}.
|
||||
error:
|
||||
NO_LOCAL_PROFILE: No existing email address is associated with this account.
|
||||
LOCAL_PROFILE: An email address is already associated with this account.
|
||||
INCORRECT_PASSWORD: Provided password was incorrect.
|
||||
talk-plugin-local-auth:
|
||||
change_password:
|
||||
change_password: "Change Password"
|
||||
@@ -43,7 +51,7 @@ en:
|
||||
email_does_not_match: "Email Address does not match"
|
||||
insert_password: "Insert Password:"
|
||||
required_field: "This field is required"
|
||||
done: "done"
|
||||
done: "Done"
|
||||
content:
|
||||
title: "Add an Email Address"
|
||||
description: "For your added security, we require users to add an email address to their accounts. Your email address will be used to:"
|
||||
@@ -59,6 +67,7 @@ en:
|
||||
subtitle: "Need to change your email address?"
|
||||
description_2: "You can change your account settings by visiting"
|
||||
path: "My Profile > Settings"
|
||||
alert: "Email Added!"
|
||||
es:
|
||||
talk-plugin-local-auth:
|
||||
change_password:
|
||||
@@ -1,5 +1,12 @@
|
||||
@custom-media --narrow-viewport (max-width: 420px);
|
||||
|
||||
.commentContent {
|
||||
composes: content from "./CommentContent.css";
|
||||
|
||||
/* Prevent zoom on narrow viewports */
|
||||
@media (--narrow-viewport) {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
|
||||
@@ -8,6 +8,7 @@ import RTE from './rte/RTE';
|
||||
import { Icon } from 'plugin-api/beta/client/components/ui';
|
||||
import { Bold, Italic, Blockquote } from './rte/features';
|
||||
import { t } from 'plugin-api/beta/client/services';
|
||||
import bowser from 'bowser';
|
||||
|
||||
class Editor extends React.Component {
|
||||
ref = null;
|
||||
@@ -40,7 +41,9 @@ class Editor extends React.Component {
|
||||
}
|
||||
});
|
||||
}
|
||||
if (this.props.isReply) {
|
||||
|
||||
// Skip IOS due to a bug, see https://www.pivotaltracker.com/story/show/157434928
|
||||
if (this.props.isReply && !bowser.ios) {
|
||||
this.ref.focus();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
.container {
|
||||
width: auto;
|
||||
max-width: 680px;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.graphiql em {
|
||||
font-family: georgia;
|
||||
}
|
||||
+27
-18
@@ -1,49 +1,58 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
|
||||
const errors = require('../../errors');
|
||||
const Assets = require('../../services/assets');
|
||||
|
||||
const body =
|
||||
'Lorem ipsum dolor sponge amet, consectetur adipiscing clam. Ut lobortis sollicitudin pillar a ornare. Curabitur dignissim vestibulum cay non rhoncus. Cras laoreet ante vel nunc hendrerit, shelf imperdiet neque egestas. Suspendisse aliquet iaculis fermentum. Talk volutpat, tellus posuere laoreet consequat, mi lacus laoreet massa, sed vehicula mauris velit non lectus. Integer non trust nec neque congue faucibus porttitor sit amet elkhorn.';
|
||||
const casual = require('casual');
|
||||
const { ErrNotFound } = require('../../errors');
|
||||
const Asset = require('../../models/asset');
|
||||
|
||||
router.get('/id/:asset_id', async (req, res, next) => {
|
||||
try {
|
||||
const asset = await Assets.findById(req.params.asset_id);
|
||||
const asset = await Asset.findOne({ id: req.params.asset_id });
|
||||
if (asset === null) {
|
||||
return next(errors.ErrNotFound);
|
||||
throw new ErrNotFound();
|
||||
}
|
||||
|
||||
res.render('dev/article', {
|
||||
title: asset.title,
|
||||
asset_id: asset.id,
|
||||
asset_url: asset.url,
|
||||
body: '',
|
||||
basePath: '/client/embed/stream',
|
||||
});
|
||||
} catch (err) {
|
||||
return next(err);
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/random', (req, res) => {
|
||||
const title = casual.title;
|
||||
|
||||
res.redirect(`./title/${title.replace(/ /g, '-')}`);
|
||||
});
|
||||
|
||||
router.get('/title/:asset_title', (req, res) => {
|
||||
return res.render('dev/article', {
|
||||
res.render('dev/article', {
|
||||
title: req.params.asset_title.split('-').join(' '),
|
||||
asset_url: '',
|
||||
asset_id: null,
|
||||
body: body,
|
||||
basePath: '/client/embed/stream',
|
||||
});
|
||||
});
|
||||
|
||||
router.get('/', async (req, res, next) => {
|
||||
let skip = req.query.skip ? parseInt(req.query.skip) : 0;
|
||||
let limit = req.query.limit ? parseInt(req.query.limit) : 25;
|
||||
|
||||
try {
|
||||
const assets = await Assets.all(skip, limit);
|
||||
const skip = req.query.skip ? parseInt(req.query.skip) : 0;
|
||||
const limit = req.query.limit ? parseInt(req.query.limit) : 6;
|
||||
|
||||
const [assets, count] = await Promise.all([
|
||||
Asset.find({})
|
||||
.sort({ created_at: 1 })
|
||||
.limit(limit)
|
||||
.skip(skip),
|
||||
Asset.count(),
|
||||
]);
|
||||
|
||||
res.render('dev/articles', {
|
||||
assets: assets,
|
||||
skip,
|
||||
limit,
|
||||
count,
|
||||
assets,
|
||||
});
|
||||
} catch (err) {
|
||||
return next(err);
|
||||
|
||||
@@ -16,8 +16,6 @@ router.get('/', staticTemplate, async (req, res) => {
|
||||
title: 'Coral Talk',
|
||||
asset_url: '',
|
||||
asset_id: '',
|
||||
body: '',
|
||||
basePath: '/static/embed/stream',
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -232,11 +232,5 @@ module.exports = class AssetsService {
|
||||
await AssetModel.remove({
|
||||
id: srcAssetID,
|
||||
});
|
||||
|
||||
// That's it!
|
||||
}
|
||||
|
||||
static all(limit = undefined) {
|
||||
return AssetModel.find({}).limit(limit);
|
||||
}
|
||||
};
|
||||
|
||||
+2
-7
@@ -3,16 +3,11 @@
|
||||
<head>
|
||||
<meta name="viewport" content="initial-scale=1, maximum-scale=1">
|
||||
<title>Talk - Coral Admin</title>
|
||||
<style media="screen">
|
||||
html, body, #root, #root > div { min-height: 100%; }
|
||||
body { margin: 0; background-color: #FAFAFA; font-family: 'Roboto', sans-serif; }
|
||||
</style>
|
||||
<%- include partials/head %>
|
||||
<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">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
|
||||
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
|
||||
<%- include partials/head %>
|
||||
<link rel="stylesheet" type="text/css" href="<%= resolve('coral-admin/bundle.css') %>">
|
||||
<%- include partials/custom-css %>
|
||||
</head>
|
||||
<body class="admin-page">
|
||||
<div id="root"></div>
|
||||
|
||||
@@ -5,13 +5,17 @@
|
||||
<meta charset="utf-8" />
|
||||
<title>GraphiQL</title>
|
||||
<meta name="robots" content="noindex" />
|
||||
<%- include ../partials/dev %>
|
||||
<style>
|
||||
html, body {
|
||||
html, body, #graphiql {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
*, ::after, ::before {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
</style>
|
||||
<link href="//cdn.jsdelivr.net/graphiql/0.9.1/graphiql.css" rel="stylesheet" />
|
||||
<script src="//cdn.jsdelivr.net/fetch/0.9.0/fetch.min.js"></script>
|
||||
@@ -20,6 +24,8 @@
|
||||
<script src="//cdn.jsdelivr.net/graphiql/0.9.1/graphiql.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<%- include ../partials/dev-nav %>
|
||||
<main id="graphiql"></main>
|
||||
<script>
|
||||
// Collect the URL parameters
|
||||
var parameters = {};
|
||||
@@ -112,8 +118,8 @@
|
||||
variables: null,
|
||||
operationName: null,
|
||||
}),
|
||||
document.body
|
||||
document.querySelector("#graphiql")
|
||||
);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
+36
-44
@@ -8,53 +8,45 @@
|
||||
<meta property="article:published" itemprop="datePublished" content="2016-11-16T11:46:06-05:00" />
|
||||
<meta property="article:modified" itemprop="dateModified" content="2016-11-16T12:09:44-05:00" />
|
||||
<meta property="article:section" itemprop="articleSection" content="The Section!" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
main {
|
||||
margin-left:auto;
|
||||
margin-right:auto;
|
||||
max-width:500px;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
<title><%= title %></title>
|
||||
<%- include ../partials/dev %>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<h1><%= title %></h1>
|
||||
<p><%= body %></p>
|
||||
<p><a href="<%= BASE_PATH %>admin">Admin</a> - <a href="<%= BASE_PATH %>dev/assets">All Assets</a></p>
|
||||
<div id='coralStreamEmbed'></div>
|
||||
<script src="<%= resolve('embed.js') %>" async onload="
|
||||
window.TalkEmbed = Coral.Talk.render(document.getElementById('coralStreamEmbed'), {
|
||||
talk: '<%= BASE_URL %>',
|
||||
asset_url: '<%= asset_url ? asset_url : '' %>',
|
||||
asset_id: '<%= asset_id ? asset_id : '' %>',
|
||||
auth_token: '',
|
||||
/**
|
||||
* You can listen to events using the example below.
|
||||
* The argument passed is the event emitter from
|
||||
* https://github.com/asyncly/EventEmitter2
|
||||
*
|
||||
* events: function(events) {
|
||||
* events.onAny(function(eventName, data) {
|
||||
* console.log(eventName, data);
|
||||
* });
|
||||
* },
|
||||
*/
|
||||
plugins_config: {
|
||||
<%- include ../partials/dev-nav %>
|
||||
<div class="container">
|
||||
<h1 class="mt-3"><%= title %></h1>
|
||||
<div id='coralStreamEmbed'></div>
|
||||
<script src="<%= resolve('embed.js') %>"></script>
|
||||
<script>
|
||||
window.TalkEmbed = Coral.Talk.render(document.getElementById('coralStreamEmbed'), {
|
||||
talk: '<%= BASE_URL %>',
|
||||
asset_url: '<%= asset_url ? asset_url : '' %>',
|
||||
asset_id: '<%= asset_id ? asset_id : '' %>',
|
||||
auth_token: '',
|
||||
/**
|
||||
* You can disable rendering slot components of a plugin by doing:
|
||||
*
|
||||
* 'talk-plugin-love': {
|
||||
* disable_components: true,
|
||||
* },
|
||||
*/
|
||||
test: 'data',
|
||||
debug: false
|
||||
}
|
||||
})
|
||||
"></script>
|
||||
</main>
|
||||
* You can listen to events using the example below.
|
||||
* The argument passed is the event emitter from
|
||||
* https://github.com/asyncly/EventEmitter2
|
||||
*
|
||||
* events: function(events) {
|
||||
* events.onAny(function(eventName, data) {
|
||||
* console.log(eventName, data);
|
||||
* });
|
||||
* },
|
||||
*/
|
||||
plugins_config: {
|
||||
/**
|
||||
* You can disable rendering slot components of a plugin by doing:
|
||||
*
|
||||
* 'talk-plugin-love': {
|
||||
* disable_components: true,
|
||||
* },
|
||||
*/
|
||||
test: 'data',
|
||||
debug: false
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+38
-12
@@ -1,14 +1,40 @@
|
||||
<html>
|
||||
<body>
|
||||
<h1>
|
||||
Asset list
|
||||
</h1>
|
||||
<% assets.forEach(function (asset) { %>
|
||||
<a href="<%= BASE_PATH %>dev/assets/id/<%= asset.id %>"><%= asset.url %></a><br />
|
||||
<% }) %>
|
||||
<p>
|
||||
(For dev use only. FYI, you can: ?skip=100&limit=25)
|
||||
</p>
|
||||
|
||||
</body>
|
||||
<head>
|
||||
<title>All Assets</title>
|
||||
<%- include ../partials/dev %>
|
||||
</head>
|
||||
<body>
|
||||
<%- include ../partials/dev-nav %>
|
||||
<div class="container">
|
||||
<div class="d-flex w-100 justify-content-between mt-3 mb-2">
|
||||
<h1 class="mb-0">All Assets</h1>
|
||||
<span class="text-muted"><%= skip + 1 %> - <%= skip + assets.length %> of <%= count %> Assets</span>
|
||||
</div>
|
||||
<div class="list-group">
|
||||
<% if (skip === 0) { %><a href="<%= BASE_PATH %>dev/assets/random" class="list-group-item list-group-item-action list-group-item-primary"><i class="fa fa-plus" aria-hidden="true"></i> Create a random article</a><% } %>
|
||||
<% assets.forEach(function (asset) { %>
|
||||
<a href="<%= BASE_PATH %>dev/assets/id/<%= asset.id %>" class="list-group-item list-group-item-action flex-column align-items-start">
|
||||
<div class="d-flex w-100 justify-content-between">
|
||||
<h5 class="mb-1"><%= asset.title %></h5>
|
||||
<small>Created <%= asset.created_at.toLocaleString('en-US') %></small>
|
||||
</div>
|
||||
<small><%= asset.url %></small>
|
||||
</a>
|
||||
<% }) %>
|
||||
</div>
|
||||
<% if (count !== assets.length) { %>
|
||||
<nav aria-label="Page navigation example" class="mt-2">
|
||||
<ul class="pagination justify-content-center">
|
||||
<% let page = 1; for (let i = 0; i < count; i += limit) { %>
|
||||
<% if (i === skip) { %>
|
||||
<li class="page-item disabled"><a class="page-link" href="#"><%= page %></a></li>
|
||||
<% } else { %>
|
||||
<li class="page-item"><a class="page-link" href="?skip=<%= i %>&limit=<%= limit %>"><%= page %></a></li>
|
||||
<% } %>
|
||||
<% page++; } %>
|
||||
</ul>
|
||||
</nav>
|
||||
<% } %>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<%- include ../partials/head %>
|
||||
<link rel="stylesheet" type="text/css" href="<%= resolve('embed/stream/default.css') %>">
|
||||
<link rel="stylesheet" type="text/css" href="<%= resolve('embed/stream/bundle.css') %>">
|
||||
<%- include ../partials/custom-css %>
|
||||
</head>
|
||||
<body class="embed-stream-page">
|
||||
<div id="talk-embed-stream-container"></div>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
|
||||
<%- include partials/head %>
|
||||
<link rel="stylesheet" type="text/css" href="<%= resolve('coral-login/bundle.css') %>">
|
||||
<%- include partials/custom-css %>
|
||||
</head>
|
||||
<body>
|
||||
<div id="talk-login-container"></div>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<%- include ./head %>
|
||||
<%- include head %>
|
||||
<link rel="stylesheet" href="https://code.getmdl.io/1.2.1/material.indigo-pink.min.css">
|
||||
<link rel="stylesheet" href="<%= BASE_PATH %>public/css/admin.css">
|
||||
<%- include custom-css %>
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<% if (locals.customCssUrl) { %><link href="<%= customCssUrl %>" rel="stylesheet" type="text/css"><% } %>
|
||||
@@ -0,0 +1,8 @@
|
||||
<nav class="navbar navbar-dark bg-dark">
|
||||
<a class="navbar-brand" href="<%= BASE_PATH %>dev"><%= organizationName %> <span class="text-muted">Organization</span></a>
|
||||
<form class="form-inline mb-0">
|
||||
<a href="<%= BASE_PATH %>admin" class="btn btn-outline-primary mr-2"><i class="fa fa-lock" aria-hidden="true"></i> Admin</a>
|
||||
<a href="<%= BASE_PATH %>api/v1/graph/iql" class="btn btn-outline-secondary mr-2 graphiql"><i class="fa fa-terminal" aria-hidden="true"></i> Graph<em>i</em>QL</a>
|
||||
<a href="<%= BASE_PATH %>dev/assets" class="btn btn-outline-secondary"><i class="fa fa-list" aria-hidden="true"></i> All Assets</a>
|
||||
</form>
|
||||
</nav>
|
||||
@@ -0,0 +1,5 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,600" rel="stylesheet">
|
||||
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous" rel="stylesheet">
|
||||
<link href="<%= BASE_PATH %>public/css/dev.css" rel="stylesheet" >
|
||||
@@ -18,9 +18,6 @@
|
||||
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,600" rel="stylesheet">
|
||||
|
||||
<%_ if (locals.customCssUrl) { _%>
|
||||
<link href="<%= customCssUrl %>" rel="stylesheet" type="text/css">
|
||||
<%_ } _%>
|
||||
<%- include data %>
|
||||
|
||||
<base href="<%= BASE_URL %>"/>
|
||||
|
||||
@@ -1828,6 +1828,13 @@ caseless@~0.12.0:
|
||||
version "0.12.0"
|
||||
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
|
||||
|
||||
casual@^1.5.19:
|
||||
version "1.5.19"
|
||||
resolved "https://registry.yarnpkg.com/casual/-/casual-1.5.19.tgz#66fac46f7ae463f468f5913eb139f9c41c58bbf2"
|
||||
dependencies:
|
||||
mersenne-twister "^1.0.1"
|
||||
moment "^2.15.2"
|
||||
|
||||
center-align@^0.1.1:
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad"
|
||||
@@ -7154,6 +7161,10 @@ merge@^1.1.3:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.0.tgz#7531e39d4949c281a66b8c5a6e0265e8b05894da"
|
||||
|
||||
mersenne-twister@^1.0.1:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/mersenne-twister/-/mersenne-twister-1.1.0.tgz#f916618ee43d7179efcf641bec4531eb9670978a"
|
||||
|
||||
metascraper-author@^3.9.2:
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-author/-/metascraper-author-3.9.2.tgz#ff2020ac428f59a875d655df3b0d4bea171fde19"
|
||||
@@ -7436,6 +7447,10 @@ moment@^2.10.3:
|
||||
version "2.19.1"
|
||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.19.1.tgz#56da1a2d1cbf01d38b7e1afc31c10bcfa1929167"
|
||||
|
||||
moment@^2.15.2:
|
||||
version "2.22.1"
|
||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.1.tgz#529a2e9bf973f259c9643d237fda84de3a26e8ad"
|
||||
|
||||
mongodb-core@2.1.17:
|
||||
version "2.1.17"
|
||||
resolved "https://registry.yarnpkg.com/mongodb-core/-/mongodb-core-2.1.17.tgz#a418b337a14a14990fb510b923dee6a813173df8"
|
||||
|
||||
Reference in New Issue
Block a user