diff --git a/package.json b/package.json index a5f55c5fc..7e2b1c422 100644 --- a/package.json +++ b/package.json @@ -19,10 +19,12 @@ }, "dependencies": { "app-module-path": "^1.0.5", + "axios": "^0.19.0", "babel-polyfill": "^6.23.0", "babel-preset-stage-2": "^6.1.18", "body-parser": "^1.14.1", "bootstrap": "^4.1.3", + "classnames": "^2.2.6", "codecov": "^3.0.0", "connect-history-api-fallback": "^1.1.0", "cookie-parser": "^1.4.0", diff --git a/src/actions/events.js b/src/actions/events.js index d3d143e86..6751b9c37 100644 --- a/src/actions/events.js +++ b/src/actions/events.js @@ -84,7 +84,7 @@ export function startFetchingEventDetails() { } export function fetchEventDetails(eventID, user = {}) { - let url = `${appSettings.api_base}/event/${eventID}/?include=keywords,location,audience,in_language,external_links,image` + let url = `${appSettings.api_base}/event/${eventID}/?include=keywords,location,audience,in_language,external_links` if(appSettings.nocache) { url += `&nocache=${Date.now()}` diff --git a/src/api/client.js b/src/api/client.js new file mode 100644 index 000000000..66022a86d --- /dev/null +++ b/src/api/client.js @@ -0,0 +1,134 @@ +import axios from 'axios' +import get from 'lodash/get' + +import store from '../store' +import CONSTANTS from '../constants' + +let authToken + +const getToken = () => { + const state = store.getState() + return get(state, 'user.token') +} + +store.subscribe(() => { + authToken = getToken() +}) + +export class ApiClient { + baseUrl + + constructor(baseUrl) { + this.baseUrl = baseUrl + authToken = getToken() + } + + getUrl = (endpoint) => { + // URLs in Django must have a trailing slash + const endsWithTrailingSlash = endpoint.substring(endpoint.length - 1) === '/' + return `${this.baseUrl}/${endpoint}${endsWithTrailingSlash ? '' : '/'}` + } + + getHeaders = () => ({ + ...CONSTANTS.API_HEADERS, + ...(authToken + ? {Authorization: `JWT ${authToken}`} + : {}), + }) + + request = async ({ + method, + endpoint, + data = {}, + headers = {}, + }) => { + const dataOrParams = ['GET', 'DELETE'].includes(method.toUpperCase()) ? 'params' : 'data' + + return axios + .request({ + method, + url: this.getUrl(endpoint), + headers: { + ...this.getHeaders(), + ...headers, + }, + [dataOrParams]: data, + }) + .then(response => ({ + data: get(response, 'data'), + error: null, + })) + } + + /** + * Make a GET request into the API. + * @param endpoint + * @param data + * @param config + * @returns {Promise} + */ + get = async (endpoint, data = {}, config = {}) => this.request({ + method: 'GET', + endpoint, + data, + ...config, + }) + + /** + * Make a POST request into the API. + * @param endpoint + * @param data + * @param config + * @returns {Promise} + */ + post = (endpoint, data = {}, config = {}) => this.request({ + method: 'POST', + endpoint, + data, + ...config, + }) + + /** + * Make a DELETE request into the API. + * @param endpoint + * @param data + * @param config + * @returns {Promise} + */ + delete = (endpoint, data = {}, config = {}) => this.request({ + method: 'DELETE', + endpoint, + data, + ...config, + }) + + /** + * Make a PUT request into the API. + * @param endpoint + * @param data + * @param config + * @returns {Promise} + */ + put = (endpoint, data = {}, config = {}) => this.request({ + method: 'PUT', + endpoint, + data, + ...config, + }) + + /** + * Make a PATCH request into the API. + * @param endpoint + * @param data + * @param config + * @returns {Promise} + */ + patch = (endpoint, data = {}, config = {}) => this.request({ + method: 'PATCH', + endpoint, + data, + ...config, + }) +} + +export default new ApiClient(appSettings.api_base) diff --git a/src/components/EventDetails/index.js b/src/components/EventDetails/index.js index 3356c4158..319814bd0 100644 --- a/src/components/EventDetails/index.js +++ b/src/components/EventDetails/index.js @@ -1,35 +1,50 @@ -import './index.scss' - import moment from 'moment' import React from 'react' import PropTypes from 'prop-types' +import get from 'lodash/get' +import { + injectIntl, + FormattedMessage, + FormattedDate, + FormattedTime, + intlShape, +} from 'react-intl' -import {injectIntl, FormattedMessage, FormattedDate, FormattedTime} from 'react-intl' -import {getStringWithLocale} from 'src/utils/locale' +import {getStringWithLocale} from '../../utils/locale' -import {mapKeywordSetToForm, mapLanguagesSetToForm} from 'src/utils/apiDataMapping.js' +import './index.scss' -let NoValue = (props) => { - let header = props.labelKey ? ( ) : null +const NoValue = (props) => { + let header = props.labelKey ? ( ) : null return (
{header} - +
) } -let CheckedValue = (props) => { - let checkIcon = props.checked ? () : () - let label = props.labelKey ? : props.label +NoValue.propTypes = { + labelKey: PropTypes.string, +} + +const CheckedValue = (props) => { + let checkIcon = props.checked ? () : ( + ) + let label = props.labelKey ? : props.label return (
{checkIcon}
) } -let MultiLanguageValue = (props) => { +CheckedValue.propTypes = { + checked: PropTypes.bool, + labelKey: PropTypes.string, + label: PropTypes.string, +} - if(props.hidden) { +const MultiLanguageValue = (props) => { + if (props.hidden) { return (
) } @@ -39,7 +54,7 @@ let MultiLanguageValue = (props) => { // Determine column size depending on the amount of language options let colClass = 'col-md-12' - if(count > 1) { + if (count > 1) { colClass = (count === 2) ? 'col-md-6' : 'col-md-4' } @@ -51,15 +66,20 @@ let MultiLanguageValue = (props) => { let val = value[key] const createHTML = () => ({__html: val}) - if(val) { - elements.push(
) + if (val) { + elements.push(
+
+ +
+
+
) } }) - if(elements.length > 0) { + if (elements.length > 0) { return (
- +
{elements}
@@ -68,7 +88,7 @@ let MultiLanguageValue = (props) => { } else { return (
- +
@@ -78,11 +98,11 @@ let MultiLanguageValue = (props) => { } } -let TextValue = (props) => { +const TextValue = (props) => { if (_.isInteger(props.value) || (props.value && props.value.length !== undefined && props.value.length > 0)) { return (
-
+
{props.value}
@@ -91,7 +111,7 @@ let TextValue = (props) => { } else { return (
-
+
@@ -100,24 +120,23 @@ let TextValue = (props) => { } } -let ImageValue = (props) => { - if(props.value !== undefined && props.value instanceof Object) { - return ( -
- -
- ) - } else { - return ( - - - - ) +const ImageValue = (props) => { + if (props.value !== undefined && props.value instanceof Object) { + return } + + return ( + + + + ) } -let OptionGroup = (props) => { +ImageValue.propTypes = { + value: PropTypes.object, +} +const OptionGroup = (props) => { let values = props.values || [] let elements = _.map(values, (val, key) => { @@ -125,35 +144,38 @@ let OptionGroup = (props) => { return () }) - if(elements.length === 0) { + if (elements.length === 0) { elements = () } return ( -
-
+
+
{elements}
) } -let DateTime = (props) => { +OptionGroup.propTypes = { + values: PropTypes.array, + labelKey: PropTypes.string, +} +const DateTime = (props) => { // TODO: if all day event show it on this field. Add a props for it - if(props.value && props.value.length !== undefined && props.value.length > 0) { - - let time = moment(props.value).tz('Europe/Helsinki'); + if (props.value && props.value.length !== undefined && props.value.length > 0) { + let time = moment(props.value).tz('Europe/Helsinki') let value = '' - if(time.isValid()) { + if (time.isValid()) { value =
- - + { } return (
- + {value} @@ -171,7 +193,7 @@ let DateTime = (props) => { } else { return (
- + @@ -180,181 +202,142 @@ let DateTime = (props) => { } } -let FormHeader = (props) => ( -
- { props.children } -
-) +const FormHeader = props => {props.children} +FormHeader.propTypes = { + children: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.object, + ]), +} -let OffersValue = (props) => { +const OffersValue = (props) => { const {offers} = props.values - if (offers && offers[0] && typeof offers[0] === 'object') { - const offersValueList = [] - for (const key in props.values.offers) { - const offerValues = ( -
- -
- ) - offersValueList.push(offerValues) - } - return ( -
- - {offersValueList} -
- ) - } else { + if (!offers || offers[0] && typeof offers[0] !== 'object') { return () } + + return ( +
+ + {props.values.offers.map((offer, key) => ( +
+ +
+ ))} +
+ ) } -class EventDetails extends React.Component { +OffersValue.propTypes = { + values: PropTypes.object, + labelKey: PropTypes.string, +} - render() { +const EventDetails = (props) => { + // NOTE: Currently don't show not selected options - let props = this.props - // NOTE: Currently don't show not selected options + // let helMainOptions = mapKeywordSetToForm(props.keywordSets, 'helfi:topics') + // let helTargetOptions = mapKeywordSetToForm(props.keywordSets, 'helfi:audiences') + // let helEventLangOptions = mapLanguagesSetToForm(props.languages) + let helfiCategories = _.map(props.values.hel_main, (id) => ( + _.find(props.rawData.keywords, (item) => (id.indexOf(item['@id']) > -1)) + )) - // let helMainOptions = mapKeywordSetToForm(props.keywordSets, 'helfi:topics') - // let helTargetOptions = mapKeywordSetToForm(props.keywordSets, 'helfi:audiences') - // let helEventLangOptions = mapLanguagesSetToForm(props.languages) - let helfiCategories = _.map(props.values.hel_main, (id) => ( - _.find(props.rawData.keywords, (item) => (id.indexOf(item['@id']) > -1)) - )) - - return ( -
- - - { props.intl.formatMessage({id: 'event-description-fields-header'}) } - -
-
- - - - - -
-
+ return ( +
+ + + {props.intl.formatMessage({id: 'event-description-fields-header'})} + - - { props.intl.formatMessage({id: 'event-datetime-fields-header'}) } - -
-
- - -
-
+ + + + + + {props.publisher && } - - { props.intl.formatMessage({id: 'event-location-fields-header'}) } - -
-
- - - -
-
+ + {props.intl.formatMessage({id: 'event-datetime-fields-header'})} + + + + + + {props.intl.formatMessage({id: 'event-location-fields-header'})} + + + + + + + {props.intl.formatMessage({id: 'event-price-fields-header'})} + + + + + {props.intl.formatMessage({id: 'event-social-media-fields-header'})} + + + + + + + {props.intl.formatMessage({id: 'event-categorization'})} + + + + + + + + {appSettings.ui_mode === 'courses' && - { props.intl.formatMessage({id: 'event-price-fields-header'}) } + {props.intl.formatMessage({id: 'audience-age-restrictions'})} -
-
- -
-
+ + - { props.intl.formatMessage({id: 'event-social-media-fields-header'}) } + {props.intl.formatMessage({id: 'enrolment-time'})} -
-
- - - -
-
+ + - { props.intl.formatMessage({id: 'event-categorization'}) } + {props.intl.formatMessage({id: 'attendee-capacity'})} -
-
- - -
- - -
-
- - {appSettings.ui_mode === 'courses' && -
- - { props.intl.formatMessage({id: 'audience-age-restrictions'})} - -
-
- - -
-
- - - { props.intl.formatMessage({id: 'enrolment-time'})} - -
-
- - -
-
- - - { props.intl.formatMessage({id: 'attendee-capacity'})} - -
-
- - -
-
-
- } -
- ) - } -} - -NoValue.propTypes = { - labelKey: PropTypes.string, -} - -CheckedValue.propTypes = { - checked: PropTypes.bool, - labelKey: PropTypes.string, - label: PropTypes.string, -} - -OptionGroup.propTypes = { - values: PropTypes.array, - labelKey: PropTypes.string, + + +
} +
+ ) } -FormHeader.propTypes = { - children: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.object, - ]), +EventDetails.propTypes = { + values: PropTypes.object, + rawData: PropTypes.object, + intl: intlShape, + publisher: PropTypes.object, } export default injectIntl(EventDetails) diff --git a/src/constants.js b/src/constants.js index b9158d712..c40ba2603 100644 --- a/src/constants.js +++ b/src/constants.js @@ -1,4 +1,8 @@ const constants = { + API_HEADERS: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }, APP_SET_FLASHMSG: 'APP_SET_FLASHMSG', APP_CLEAR_FLASHMSG: 'APP_CLEAR_FLASHMSG', diff --git a/src/i18n/en.json b/src/i18n/en.json index 0003c081a..283b8d795 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -58,7 +58,9 @@ "event-provider": "Event organizer", "event-provider-input": "Event organizer (if different than the publisher)", "event-publisher": "Event publisher", - + "event-publisher-info": "Publisher: {publisher}, {publishedAt}", + "event-publisher-info-with-created-by": "Publisher: {publisher} / {createdBy}, {publishedAt}", + "events-management": "Manage events", "events-management-prompt": "to manage events.", "events-management-description": "Browse and edit drafts and published events of your organization.", diff --git a/src/i18n/fi.json b/src/i18n/fi.json index 1ce95b96f..62b81f838 100644 --- a/src/i18n/fi.json +++ b/src/i18n/fi.json @@ -58,7 +58,8 @@ "event-provider": "Tapahtuman järjestäjä", "event-provider-input": "Tapahtuman järjestäjä (jos eri kuin julkaisija)", "event-publisher": "Tapahtuman julkaisija", - + "event-publisher-info": "Julkaisija: {publisher}, {publishedAt}", + "event-publisher-info-with-created-by": "Julkaisija: {publisher} / {createdBy}, {publishedAt}", "events-management": "Tapahtumien hallinta", "events-management-prompt": "muokataksesi tapahtumia.", "events-management-description": "Selaa ja muokkaa oman organisaatiosi julkisia tapahtumia sekä luonnoksia. Voit lisätä uuden tapahtuman yläpalkista.", diff --git a/src/index.js b/src/index.js index 64b577c3c..c8ea8141d 100644 --- a/src/index.js +++ b/src/index.js @@ -1,17 +1,12 @@ - import React from 'react' import ReactDOM from 'react-dom' import {Route} from 'react-router' import PropTypes from 'prop-types' - -import {Link, withRouter} from 'react-router-dom' -import createHistory from 'history/createBrowserHistory' //'history/createHashHistory' - +import {withRouter} from 'react-router-dom' +import createHistory from 'history/createBrowserHistory' import {createStore, combineReducers, applyMiddleware, compose} from 'redux' import {Provider, connect} from 'react-redux' - -import {ConnectedRouter, routerReducer, routerMiddleware, push} from 'react-router-redux' - +import {ConnectedRouter, routerReducer, routerMiddleware} from 'react-router-redux' import thunk from 'redux-thunk' import reducers from './reducers' @@ -35,22 +30,7 @@ import {Modal, Button, Glyphicon} from 'react-bootstrap'; // translation import IntlProviderWrapper from './components/IntlProviderWrapper' - -const history = createHistory() - -const allReducers = combineReducers(Object.assign({}, reducers, { - router: routerReducer, -})) - -const allMiddlewares = compose( - applyMiddleware(thunk), - applyMiddleware(routerMiddleware(history)), - typeof window === 'object' && typeof window.devToolsExtension !== 'undefined' ? window.devToolsExtension() : f => f -) - -const store = createStore(allReducers, allMiddlewares) - - +import store, {history} from './store' // Setup actor for validation. Actor is a viewless component which can listen to store changes // and send new actions accordingly. Bind the store as this for function diff --git a/src/store.js b/src/store.js new file mode 100644 index 000000000..e186a13c2 --- /dev/null +++ b/src/store.js @@ -0,0 +1,21 @@ +import createHistory from 'history/createBrowserHistory' +import {applyMiddleware, combineReducers, compose, createStore} from 'redux' +import reducers from './reducers' +import {routerMiddleware, routerReducer} from 'react-router-redux' +import thunk from 'redux-thunk' + +export const history = createHistory() + +const allReducers = combineReducers(Object.assign({}, reducers, { + router: routerReducer, +})) + +const allMiddlewares = compose( + applyMiddleware(thunk), + applyMiddleware(routerMiddleware(history)), + typeof window === 'object' && typeof window.devToolsExtension !== 'undefined' ? window.devToolsExtension() : f => f +) + +const store = createStore(allReducers, allMiddlewares) + +export default store diff --git a/src/utils/locale.js b/src/utils/locale.js index 60b11b4e7..64c0ca692 100644 --- a/src/utils/locale.js +++ b/src/utils/locale.js @@ -7,14 +7,15 @@ import {get} from 'lodash' * // let label = getStringWithLocale(this.props, 'editor.values.name', 'fi') * * @param {object} obj multi language field - * @param {string} fieldpath string path for the field + * @param {string} fieldPath string path for the field * @param {string} locale 'fi', 'sv' or 'en' - * @return {string} language string + * @param {string} defaultValue + * @return {string} language string */ -export function getStringWithLocale(obj, fieldpath = '', locale = 'fi', defaultValue = '') { - let field = get(obj, fieldpath, {}) +export function getStringWithLocale(obj, fieldPath = '', locale = 'fi', defaultValue = '') { + let field = get(obj, fieldPath, {}) - if(typeof field === 'object' && field) { + if (typeof field === 'object' && field) { return field[locale] || field.fi || field.sv || field.en || defaultValue } diff --git a/src/views/Editor/index.scss b/src/views/Editor/index.scss index e74c36c7a..b2afe3462 100644 --- a/src/views/Editor/index.scss +++ b/src/views/Editor/index.scss @@ -3,7 +3,6 @@ $actionBtnMargin: 0 10px; $actionBtnHeight: 64px; .editor-page { - font-weight: 300; background-color: #ffffff; diff --git a/src/views/Event/index.js b/src/views/Event/index.js index 3c8cde7bd..c9f500b4c 100644 --- a/src/views/Event/index.js +++ b/src/views/Event/index.js @@ -1,57 +1,73 @@ -import './index.scss' - import React from 'react' import {connect} from 'react-redux' import EventDetails from 'src/components/EventDetails' import moment from 'moment' import PropTypes from 'prop-types' - +import get from 'lodash/get' import {FormattedMessage, injectIntl, intlShape} from 'react-intl' - import {Button} from 'material-ui' import Tooltip from 'material-ui/Tooltip' import {push} from 'react-router-redux' +import classNames from 'classnames' -import {fetchEventDetails as fetchEventDetailsAction} from 'src/actions/events.js' +import {fetchEventDetails as fetchEventDetailsAction} from 'src/actions/events' import { replaceData as replaceDataAction, - deleteEvent as deleteEventAction, + deleteEvent as deleteEventAction, cancelEvent as cancelEventAction, } from 'src/actions/editor.js' import {fetchSubEvents as fetchSubEventsAction} from 'src/actions/subEvents' - -import { - confirmAction, - clearFlashMsg as clearFlashMsgAction, -} from 'src/actions/app.js' - +import {confirmAction} from 'src/actions/app.js' import {getStringWithLocale} from 'src/utils/locale' import {mapAPIDataToUIFormat} from 'src/utils/formDataMapping.js' import {checkEventEditability} from 'src/utils/checkEventEditability.js' - +import client from '../../api/client' import constants from 'src/constants' +import './index.scss' + class EventPage extends React.Component { + state = { + publisher: null, + } - UNSAFE_componentWillMount() { - const {match, fetchEventDetails, user, fetchSubEvents} = this.props + componentDidMount() { + const { + match, + fetchEventDetails, + user, + fetchSubEvents, + } = this.props fetchEventDetails(match.params.eventId, user) fetchSubEvents(this.props.match.params.eventId, user) } + componentDidUpdate(prevProps) { + const publisherId = get(this.props, 'events.event.publisher') + const oldPublisherId = get(prevProps, 'events.event.publisher') + + if (publisherId && publisherId !== oldPublisherId) { + client.get(`organization/${publisherId}`).then(response => { + this.setState({ + publisher: response.data, + }) + }) + } + } + copyAsTemplate() { - const {events:{event}, replaceData, routerPush} = this.props - if(event) { + const {events: {event}, replaceData, routerPush} = this.props + if (event) { replaceData(event) routerPush(`/event/create/new`) } } editEvent() { - const {events:{event}, replaceData, routerPush} = this.props - if(event) { - replaceData(event) + const {events: {event}, replaceData, routerPush} = this.props + if (event) { + replaceData(event) routerPush(`/event/update/${event.id}`) } } @@ -59,8 +75,8 @@ class EventPage extends React.Component { getActionButtons() { let {eventIsEditable, eventEditabilityExplanation} = checkEventEditability(this.props.user, this.props.events.event) let buttons =
- { this.getDeleteButton(!eventIsEditable) } - { this.getCancelButton(!eventIsEditable) } + {this.getDeleteButton(!eventIsEditable)} + {this.getCancelButton(!eventIsEditable)}
return (
@@ -74,8 +90,8 @@ class EventPage extends React.Component { } confirmCancel() { - const {user, events, cancelEvent} = this.props; - const eventId = this.props.match.params.eventId; + const {user, events, cancelEvent} = this.props + const eventId = this.props.match.params.eventId // TODO: maybe do a decorator for confirmable actions etc...? this.props.confirm( 'confirm-cancel', @@ -91,8 +107,8 @@ class EventPage extends React.Component { confirmDelete() { // TODO: maybe do a decorator for confirmable actions etc...? - const eventId = this.props.match.params.eventId; - const {user, deleteEvent, events} = this.props; + const eventId = this.props.match.params.eventId + const {user, deleteEvent, events} = this.props this.props.confirm( 'confirm-delete', @@ -120,91 +136,111 @@ class EventPage extends React.Component { return warningText + subEventWarning } - render() { - const user = this.props.user - - let event = mapAPIDataToUIFormat(this.props.events.event) - - // To prevent 'Can't access field of undefined errors' - event.location = event.location || {} - // Tooltip is empty if the event is editable - let {eventIsEditable, eventEditabilityExplanation} = checkEventEditability(user, event) + getPublishedText = () => { + const {events: {event}, intl} = this.props + const {publisher} = this.state - // Add necessary badges - let draftClass = event.publication_status == constants.PUBLICATION_STATUS.DRAFT ? 'event-page draft' : 'event-page' - let draftBadge = null - if (event.publication_status === constants.PUBLICATION_STATUS.DRAFT) { - draftBadge = () + if (!publisher) { + return null } - let cancelledClass = event.publication_status == constants.EVENT_STATUS.CANCELLED ? 'event-page' : 'event-page' - let cancelledBadge = null - if (event.event_status === constants.EVENT_STATUS.CANCELLED) { - cancelledBadge = () + + const values = { + publisher: publisher.name, + createdBy: get(event, 'created_by', ''), + publishedAt: moment(event.last_modified_time).format('D.M.YYYY HH:mm'), } - if(this.props.events.eventError) { + return intl.formatMessage({ + id: values.createdBy ? 'event-publisher-info-with-created-by' : 'event-publisher-info', + }, values); + } + + render() { + const {user} = this.props + let event = mapAPIDataToUIFormat(this.props.events.event) + + if (!event || !event.name) { return ( -
-

-
-

+
+
+

+
) } - const editEventButton = - const cancelEventButton = - const deleteEventButton = - if(event && event.name) { + if (this.props.events.eventError) { return ( -
-
+
+
+

+
+
+ ) + } + + // Tooltip is empty if the event is editable + let {eventIsEditable, eventEditabilityExplanation} = checkEventEditability(user, event) + + const isDraft = event.publication_status === constants.PUBLICATION_STATUS.DRAFT + const isCancelled = event.publication_status === constants.EVENT_STATUS.CANCELLED + + const editEventButton = + const cancelEventButton = + const deleteEventButton = + + const publishedText = this.getPublishedText(); + return ( +
+
+

- {cancelledBadge} - {draftBadge} - { getStringWithLocale(event, 'name') } + {isCancelled && } + {isDraft && } + {getStringWithLocale(event, 'name')}

-
- -
-
- {eventIsEditable ? cancelEventButton : - - {cancelEventButton} - - } - {eventIsEditable ? deleteEventButton : - - {deleteEventButton} - - } -
-
- {eventIsEditable ? editEventButton : - - {editEventButton} - - } - -
+
+
+ {eventIsEditable ? cancelEventButton : + + {cancelEventButton} + + } + {eventIsEditable ? deleteEventButton : + + {deleteEventButton} + + } +
+
+ {eventIsEditable ? editEventButton : + + {editEventButton} + + } +
-
- +
+ {publishedText}
+
- ) - } - else { - return ( -
-

-
-

-
- ) - } +
+ ) } } diff --git a/src/views/Event/index.scss b/src/views/Event/index.scss index 3d95e407b..4d0ec5702 100644 --- a/src/views/Event/index.scss +++ b/src/views/Event/index.scss @@ -23,7 +23,7 @@ $buttonActionMargin: 10px; } pre { - margin: 2rem 0rem + margin: 2rem 0 } .highlighted-block { @@ -35,6 +35,11 @@ $buttonActionMargin: 10px; color: #5a5959; } + + .published-information { + text-align: right; + margin: 20px 10px; + } } .draft { diff --git a/yarn.lock b/yarn.lock index 1595a871c..c32b5252a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -628,6 +628,14 @@ aws4@^1.2.1, aws4@^1.6.0, aws4@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" +axios@^0.19.0: + version "0.19.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.0.tgz#8e09bff3d9122e133f7b8101c8fbdd00ed3d2ab8" + integrity sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ== + dependencies: + follow-redirects "1.5.10" + is-buffer "^2.0.2" + babel-cli@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-cli/-/babel-cli-6.26.0.tgz#502ab54874d7db88ad00b887a06383ce03d002f1" @@ -1980,7 +1988,7 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -classnames@^2.2.4, classnames@^2.2.5: +classnames@^2.2.4, classnames@^2.2.5, classnames@^2.2.6: version "2.2.6" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" @@ -3555,6 +3563,13 @@ flux-standard-action@^0.6.0: dependencies: lodash.isplainobject "^3.2.0" +follow-redirects@1.5.10: + version "1.5.10" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a" + integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ== + dependencies: + debug "=3.1.0" + follow-redirects@^1.0.0: version "1.5.9" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.9.tgz#c9ed9d748b814a39535716e531b9196a845d89c6" @@ -4394,6 +4409,11 @@ is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" +is-buffer@^2.0.2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" + integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== + is-builtin-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe"