diff --git a/client/src/components/Background/Background.jsx b/client/src/components/Background/Background.jsx
index 175e4c17..f3dde5fd 100644
--- a/client/src/components/Background/Background.jsx
+++ b/client/src/components/Background/Background.jsx
@@ -4,6 +4,8 @@ import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
+import { ProjectBackgroundTypes } from '../../constants/Enums';
+
import styles from './Background.module.scss';
import globalStyles from '../../styles.module.scss';
@@ -11,7 +13,8 @@ const Background = ({ type, name, imageUrl }) => (
{
- const data = {
+ onUpdate({
backgroundImage: null,
- };
-
- // TODO: move to services?
- if (project.background && project.background.type === 'image') {
- data.background = null;
- }
-
- onUpdate(data);
- }, [project.background, onUpdate]);
+ });
+ }, [onUpdate]);
if (step) {
if (step) {
diff --git a/client/src/components/Project/ActionsPopup/EditBackgroundStep.jsx b/client/src/components/Project/ActionsPopup/EditBackgroundStep.jsx
index b3219e24..d50be73a 100644
--- a/client/src/components/Project/ActionsPopup/EditBackgroundStep.jsx
+++ b/client/src/components/Project/ActionsPopup/EditBackgroundStep.jsx
@@ -9,6 +9,7 @@ import { Button, Image } from 'semantic-ui-react';
import { FilePicker, Popup } from '../../../lib/custom-ui';
import ProjectBackgroundGradients from '../../../constants/ProjectBackgroundGradients';
+import { ProjectBackgroundTypes } from '../../../constants/Enums';
import styles from './EditBackgroundStep.module.scss';
import globalStyles from '../../../styles.module.scss';
@@ -30,15 +31,12 @@ const EditBackgroundStep = React.memo(
const handleGradientClick = useCallback(
(_, { value }) => {
const background = {
- type: 'gradient',
+ type: ProjectBackgroundTypes.GRADIENT,
name: value,
};
if (!dequal(background, defaultValue)) {
- onUpdate({
- type: 'gradient',
- name: value,
- });
+ onUpdate(background);
}
},
[defaultValue, onUpdate],
@@ -46,7 +44,7 @@ const EditBackgroundStep = React.memo(
const handleImageClick = useCallback(() => {
const background = {
- type: 'image',
+ type: ProjectBackgroundTypes.IMAGE,
};
if (!dequal(background, defaultValue)) {
@@ -93,7 +91,7 @@ const EditBackgroundStep = React.memo(
className={classNames(
styles.gradientButton,
defaultValue &&
- defaultValue.type === 'gradient' &&
+ defaultValue.type === ProjectBackgroundTypes.GRADIENT &&
gradient === defaultValue.name &&
styles.gradientButtonActive,
globalStyles[`background${upperFirst(camelCase(gradient))}`],
diff --git a/client/src/components/Project/ActionsPopup/EditBackgroundStep.module.scss b/client/src/components/Project/ActionsPopup/EditBackgroundStep.module.scss
index 6b085b38..dcc3ff2d 100644
--- a/client/src/components/Project/ActionsPopup/EditBackgroundStep.module.scss
+++ b/client/src/components/Project/ActionsPopup/EditBackgroundStep.module.scss
@@ -66,6 +66,10 @@
.image {
cursor: pointer;
margin-bottom: 8px;
+
+ &:hover {
+ opacity: 0.9;
+ }
}
.imageLabel {
diff --git a/client/src/components/Projects/Projects.jsx b/client/src/components/Projects/Projects.jsx
index a4bc8d8b..e11b711f 100755
--- a/client/src/components/Projects/Projects.jsx
+++ b/client/src/components/Projects/Projects.jsx
@@ -8,6 +8,7 @@ import { Link } from 'react-router-dom';
import { Container, Grid } from 'semantic-ui-react';
import Paths from '../../constants/Paths';
+import { ProjectBackgroundTypes } from '../../constants/Enums';
import { ReactComponent as PlusIcon } from '../../assets/images/plus-icon.svg';
import styles from './Projects.module.scss';
@@ -33,7 +34,7 @@ const Projects = React.memo(({ items, isEditable, onAdd }) => {
styles.card,
styles.open,
item.background &&
- item.background.type === 'gradient' &&
+ item.background.type === ProjectBackgroundTypes.GRADIENT &&
globalStyles[`background${upperFirst(camelCase(item.background.name))}`],
)}
style={{
diff --git a/client/src/constants/Enums.js b/client/src/constants/Enums.js
index a7898eb8..400c252d 100755
--- a/client/src/constants/Enums.js
+++ b/client/src/constants/Enums.js
@@ -1,4 +1,8 @@
-// eslint-disable-next-line import/prefer-default-export
+export const ProjectBackgroundTypes = {
+ GRADIENT: 'gradient',
+ IMAGE: 'image',
+};
+
export const ActionTypes = {
CREATE_CARD: 'createCard',
MOVE_CARD: 'moveCard',
diff --git a/client/src/models/Project.js b/client/src/models/Project.js
index 4e616d37..1558cc84 100755
--- a/client/src/models/Project.js
+++ b/client/src/models/Project.js
@@ -1,6 +1,7 @@
import { Model, attr, many } from 'redux-orm';
import ActionTypes from '../constants/ActionTypes';
+import { ProjectBackgroundTypes } from '../constants/Enums';
export default class extends Model {
static modelName = 'Project';
@@ -28,10 +29,20 @@ export default class extends Model {
});
break;
- case ActionTypes.PROJECT_UPDATE:
- Project.withId(payload.id).update(payload.data);
+ case ActionTypes.PROJECT_UPDATE: {
+ const project = Project.withId(payload.id);
+ project.update(payload.data);
+
+ if (
+ payload.data.backgroundImage === null &&
+ project.background &&
+ project.background.type === ProjectBackgroundTypes.IMAGE
+ ) {
+ project.background = null;
+ }
break;
+ }
case ActionTypes.PROJECT_DELETE:
Project.withId(payload.id).deleteWithRelated();
diff --git a/server/api/controllers/projects/update.js b/server/api/controllers/projects/update.js
index 0845d004..54f12f91 100755
--- a/server/api/controllers/projects/update.js
+++ b/server/api/controllers/projects/update.js
@@ -15,9 +15,35 @@ module.exports = {
type: 'string',
isNotEmptyString: true,
},
- // TODO: add validation
background: {
type: 'json',
+ custom: (value) => {
+ if (_.isNull(value)) {
+ return true;
+ }
+
+ if (!_.isPlainObject(value)) {
+ return false;
+ }
+
+ if (!Project.BACKGROUND_TYPES.includes(value.type)) {
+ return false;
+ }
+
+ if (
+ value.type === 'gradient' &&
+ _.size(value) === 2 &&
+ Project.BACKGROUND_GRADIENTS.includes(value.name)
+ ) {
+ return true;
+ }
+
+ if (value.type === 'image' && _.size(value) === 1) {
+ return true;
+ }
+
+ return false;
+ },
},
backgroundImage: {
type: 'json',
diff --git a/server/api/helpers/update-project.js b/server/api/helpers/update-project.js
index f94f1d6b..d98fb4c9 100644
--- a/server/api/helpers/update-project.js
+++ b/server/api/helpers/update-project.js
@@ -11,7 +11,7 @@ module.exports = {
type: 'json',
custom: (value) =>
_.isPlainObject(value) &&
- /* _.isUndefined(value.background) || _.isNull(value.background) && */
+ (_.isUndefined(value.background) || _.isPlainObject(value.background)) &&
(_.isUndefined(value.backgroundImage) || _.isNull(value.backgroundImage)),
required: true,
},
@@ -20,6 +20,10 @@ module.exports = {
},
},
+ exits: {
+ invalidParams: {},
+ },
+
async fn(inputs, exits) {
if (!_.isUndefined(inputs.values.backgroundImage)) {
/* eslint-disable no-param-reassign */
@@ -33,9 +37,37 @@ module.exports = {
inputs.values.background = {
type: 'image',
};
+ } else if (
+ _.isNull(inputs.values.backgroundImageDirname) &&
+ inputs.record.background &&
+ inputs.record.background.type === 'image'
+ ) {
+ inputs.values.background = null; // eslint-disable-line no-param-reassign
}
- const project = await Project.updateOne(inputs.record.id).set(inputs.values);
+ let project;
+ if (inputs.values.background && inputs.values.background.type === 'image') {
+ if (_.isNull(inputs.values.backgroundImageDirname)) {
+ throw 'invalidParams';
+ }
+
+ if (_.isUndefined(inputs.values.backgroundImageDirname)) {
+ project = await Project.updateOne({
+ id: inputs.record.id,
+ backgroundImageDirname: {
+ '!=': null,
+ },
+ }).set(inputs.values);
+
+ if (!project) {
+ delete inputs.values.background; // eslint-disable-line no-param-reassign
+ }
+ }
+ }
+
+ if (!project) {
+ project = await Project.updateOne(inputs.record.id).set(inputs.values);
+ }
if (project) {
if (
diff --git a/server/api/models/Project.js b/server/api/models/Project.js
index ea895779..ff12e0a1 100755
--- a/server/api/models/Project.js
+++ b/server/api/models/Project.js
@@ -5,7 +5,40 @@
* @docs :: https://sailsjs.com/docs/concepts/models-and-orm/models
*/
+const BACKGROUND_TYPES = ['gradient', 'image'];
+
+const BACKGROUND_GRADIENTS = [
+ 'old-lime',
+ 'ocean-dive',
+ 'tzepesch-style',
+ 'jungle-mesh',
+ 'strawberry-dust',
+ 'purple-rose',
+ 'sun-scream',
+ 'warm-rust',
+ 'sky-change',
+ 'green-eyes',
+ 'blue-xchange',
+ 'blood-orange',
+ 'sour-peel',
+ 'green-ninja',
+ 'algae-green',
+ 'coral-reef',
+ 'steel-grey',
+ 'heat-waves',
+ 'velvet-lounge',
+ 'purple-rain',
+ 'blue-steel',
+ 'blueish-curve',
+ 'prism-light',
+ 'green-mist',
+ 'red-curtain',
+];
+
module.exports = {
+ BACKGROUND_TYPES,
+ BACKGROUND_GRADIENTS,
+
attributes: {
// ╔═╗╦═╗╦╔╦╗╦╔╦╗╦╦ ╦╔═╗╔═╗
// ╠═╝╠╦╝║║║║║ ║ ║╚╗╔╝║╣ ╚═╗