Skip to content

Commit

Permalink
Implement alerts
Browse files Browse the repository at this point in the history
  • Loading branch information
jsmesami committed Mar 2, 2024
1 parent ca01798 commit 5eb8882
Show file tree
Hide file tree
Showing 10 changed files with 81 additions and 14 deletions.
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"css-loader": "^6.5.1",
"mini-css-extract-plugin": "^2.4.5",
"node-sass-tilde-importer": "^1.0.2",
"object-hash": "^3.0.0",
"postcss": "^8.3.11",
"postcss-loader": "^8.1.0",
"postcss-preset-env": "^9.0.0",
Expand Down
23 changes: 23 additions & 0 deletions tumbs/static/js/cms/components/Alerts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from "react";
import * as R from "ramda";
import { useDispatch, useSelector } from "react-redux";
import { actions as alertsActions } from "../slices/alerts";
import Alert from "react-bootstrap/Alert";

const Alerts = () => {
const dispatch = useDispatch();
const alerts = useSelector((state) => state.alerts.list);
const dismiss = (id) => dispatch(alertsActions.removeAlert(id));

return (
<div className="alerts row container-md">
{R.reverse(alerts).map(({ id, content, severity }) => (
<Alert key={id} variant={severity} dismissible onClose={() => dismiss(id)}>
{content}
</Alert>
))}
</div>
);
};

export default Alerts;
2 changes: 2 additions & 0 deletions tumbs/static/js/cms/components/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from "react";
import { useDispatch } from "react-redux";
import { actions as newWebsiteActions } from "../slices/newWebsiteModal";
import Button from "react-bootstrap/Button";
import Alerts from "./Alerts";
import NewWebsiteModal from "./NewWebsiteModal";
import SelectWebsite from "./SelectWebsite";

Expand All @@ -11,6 +12,7 @@ const App = () => {

return (
<>
<Alerts />
<SelectWebsite />
<Button variant="primary" onClick={showNewWebsiteModal}>
Create site
Expand Down
6 changes: 3 additions & 3 deletions tumbs/static/js/cms/components/NewWebsiteModal.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { actions as alertsActions } from "../slices/alerts";
import { actions as newWebsiteActions } from "../slices/newWebsiteModal";
import { actions as websitesActions } from "../slices/websites";
import Button from "react-bootstrap/Button";
Expand Down Expand Up @@ -30,12 +31,11 @@ const NewWebsiteModal = () => {
setStatus("success");
dispatch(websitesActions.addWebsite(data));
dispatch(websitesActions.setCurrent(data.id));
// TODO: display success notification
hideModal();
},
onError: (_err) => {
onError: (err) => {
setStatus("error");
// TODO: display error notification
dispatch(alertsActions.addAlert({ content: `Could not add website: ${err}`, severity: "danger" }));
// TODO: notify Sentry
hideModal();
},
Expand Down
4 changes: 1 addition & 3 deletions tumbs/static/js/cms/network.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ export const request = (endpoint, { payload = {}, onSuccess = null, onError = nu
})
.then((response) => {
if (response.ok) return response.json();

onError && onError(`${response.status} ${response.statusText}`);
return Promise.reject(response);
return Promise.reject(response.statusText);
})
.then((data) => {
onSuccess && onSuccess(data);
Expand Down
26 changes: 26 additions & 0 deletions tumbs/static/js/cms/slices/alerts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { createSlice } from "@reduxjs/toolkit";
import * as R from "ramda";
import hash from "object-hash";

export const slice = createSlice({
name: "alerts",
initialState: {
list: [],
},
reducers: {
addAlert: (state, { payload }) => {
const id = hash.MD5(payload);
const exists = R.find(R.propEq(id, "id"))(state.list);
if (!exists) state.list.push({ id: id, ...payload });
},
removeAlert: (state, { payload }) => {
state.list = R.reject(R.propEq(payload, "id"))(state.list);
},
removeAll: (state) => {
state.list = [];
},
},
});

export const actions = slice.actions;
export const reducer = slice.reducer;
6 changes: 4 additions & 2 deletions tumbs/static/js/cms/store.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { configureStore } from "@reduxjs/toolkit";
import { reducer as websitesReducer } from "./slices/websites";
import { reducer as alertsReducer } from "./slices/alerts";
import { reducer as newWebsiteReducer } from "./slices/newWebsiteModal";
import { reducer as websitesReducer } from "./slices/websites";

const container = document.getElementById("cms");
const initData = JSON.parse(container.dataset.init);
Expand All @@ -11,7 +12,8 @@ export const ENDPOINTS = initData.endpoints;

export default configureStore({
reducer: {
websites: websitesReducer,
alerts: alertsReducer,
newWebsiteModal: newWebsiteReducer,
websites: websitesReducer,
},
});
5 changes: 5 additions & 0 deletions tumbs/static/sass/project.scss
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
@import 'bs';

.alerts {
position: fixed;
bottom: 0;
}
12 changes: 6 additions & 6 deletions tumbs/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<a class="nav-link {% block websites_active %}{% endblock websites_active %}"
href="{% url "websites:websites_cms" %}">{% trans "My Site" %}</a>
</li>

<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" role="button" id="customerDropdownButton"
data-bs-toggle="dropdown" aria-label="{% trans 'Customer' %}" aria-expanded="false">
Expand All @@ -23,25 +23,25 @@
<li><a class="dropdown-item" href="{% url "accounts:sign_out" %}">{% trans "Sign out" %}</a></li>
</ul>
</li>

{% else %}

<li class="nav-item">
<a class="nav-link" href="{% url "accounts:sign_up" %}">{% trans "Sign up" %}</a>
</li>
<li class="nav-item">
<a class="btn btn-outline-light" href="{% url "accounts:sign_in" %}">{% trans "Sign in" %}</a>
</li>

{% endif %}
</ul>
</div>
</nav>

<div class="container-fluid">
{% if messages %}
<div class="alerts">
{% for message in messages %}
<div class="alerts row container-md">
{% for message in messages reversed %}
<div class="alert alert-dismissible {% if message.tags %}alert-{{ message.tags }}{% endif %}">
{{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="{% trans 'Close' %}">
Expand Down

0 comments on commit 5eb8882

Please sign in to comment.