Skip to content

Commit

Permalink
Global tag editing may need renaming...
Browse files Browse the repository at this point in the history
  • Loading branch information
deltaepsilon committed Jan 8, 2018
1 parent 6d024f2 commit 64ae92c
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 37 deletions.
7 changes: 2 additions & 5 deletions firestore.rules
@@ -1,14 +1,11 @@
service cloud.firestore {
match /databases/{database}/documents {
match /uploads {
allow write: if request.auth.token.admin == true ;
}

match /uploads/{document=**} {
allow write: if request.auth.token.admin == true ;
allow read;
}

match /users {
match /users/{document=**} {
allow read, write: if request.auth.token.admin == true ;
}
}
Expand Down
131 changes: 101 additions & 30 deletions src/components/tags/tags.component.js
Expand Up @@ -6,6 +6,8 @@ import { store, actions, mappedActions } from '../../datastore';
import linkState from 'linkstate';
import { updateTagsQuery } from '../../queries';

const { updateImage } = mappedActions;

// Preact Material
import TextField from 'preact-material-components/TextField';
import Button from 'preact-material-components/Button';
Expand All @@ -20,13 +22,17 @@ export default connect('environment,images,selection', actions)(
}, 1000);
} else {
const selectedImages = images.filter(image => selection.has(image.__id));
const items = selectedImages.map(getItem);
const items = selectedImages.map(getItem({ environment }));
const tags = selectedImages.reduce((tags, image) => {
if (image.tags) {
image.tags.forEach(tag => tags.add(tag));
}
return tags;
}, new Set());
const globalTagItems = Array.from(tags).map(getGlobalTagItem({ environment, images }));
return (
<div>
<form
class={style.form}
onSubmit={e => handleSubmit(e, { environment, images, selection })}
>
<form class={style.form} onSubmit={handleSubmit({ environment, images, selection })}>
<TextField
className={style.tagsInput}
type="text"
Expand All @@ -35,41 +41,106 @@ export default connect('environment,images,selection', actions)(
/>
<Button type="submit">Add Tag</Button>
</form>
<ul class={style.globalTagItems}>{globalTagItems}</ul>
<ul class={style.list}>{items}</ul>
</div>
);
}
}
);

function handleSubmit(e, { environment, images, selection }) {
e.preventDefault();
function handleSubmit({ environment, images, selection }) {
return e => {
e.preventDefault();

const input = e.target.querySelector('input');
let hashtag = input.value;
hashtag = hashtag.toLowerCase();
hashtag = hashtag.replace(/[^a-z,0-9]/g, '');

input.value = '';
input.focus();

selection.forEach(id => {
const image = images.find(image => image.__id == id);
const tags = new Set(images.tags || []);
tags.add(hashtag);
updateTagsQuery({ environment, id, tags });
});
};
}

function getItem({ environment }) {
return image => {
const version = image.versions.x200;
const name = image.name.split('/').pop();
const tagItems = image.tags.map(getTagItem({ environment, image }));

const input = e.target.querySelector('input');
let hashtag = input.value;
hashtag = hashtag.toLowerCase();
hashtag = hashtag.replace(/[^a-z,0-9]/g, '');
return (
<li>
<div class={style.image} style={`background: url(${version.url})`} />
<div class={style.secondary}>
<h3>{name}</h3>
<ul class={style.tagItems}>{tagItems}</ul>
</div>
</li>
);
};
}

function getTagItem({ environment, image }) {
return tag => {
return (
<li class={style.tagItem}>
<img
src="/assets/svg/delete.svg"
alt="delete"
onClick={handleTagClick({ environment, image, tag })}
/>
<span>#{tag}</span>
</li>
);
};
}

function handleTagClick({ environment, image, tag }) {
return e => {
const tags = new Set(image.tags || []);
tags.delete(tag);

optimisticUpdate({ image, tags });
updateTagsQuery({ environment, tags, id: image.__id });
};
}

function getGlobalTagItem({ environment, images }) {
return tag => {
return (
<li class={style.tagItem}>
<img
src="/assets/svg/delete.svg"
alt="delete"
onClick={handleGlobalTagClick({ environment, images, tag })}
/>
<span>#{tag}</span>
</li>
);
};
}

input.value = '';
input.focus();
function handleGlobalTagClick({ environment, images, tag }) {
return e => {
images.forEach(image => {
const tags = new Set(image.tags || []);
tags.delete(tag);

selection.forEach(id => {
const image = images.find(image => image.__id == id);
const tags = new Set(images.tags || []);
tags.add(hashtag);
updateTagsQuery({ environment, id, tags });
});
optimisticUpdate({ image, tags });
updateTagsQuery({ environment, tags, id: image.__id });
});
};
}

function getItem(image) {
const version = image.versions.x200;
const name = image.name.split('/').pop();
return (
<li>
<div class={style.image} style={`background: url(${version.url})`} />
<div class={style.secondary}>
<h3>{name}</h3>
</div>
</li>
);
function optimisticUpdate({ image, tags }) {
image.tags = Array.from(tags);
updateImage(image);
}
29 changes: 27 additions & 2 deletions src/components/tags/tags.scss
@@ -1,13 +1,16 @@
.form {
display: flex;
align-items: center;

}

.tagsInput {
flex-grow: 1;
}

.globalTagItems {
padding: 0;
}

.list {
padding: 0;
list-style: none;
Expand All @@ -16,11 +19,14 @@
display: flex;
margin-bottom: 1rem;
}

}

.secondary {
padding: 0 1rem;

h3 {
margin-top: 0;
}
}

.image {
Expand All @@ -30,3 +36,22 @@
background-repeat: no-repeat;
background-color: #fafafa;
}

.tagItems {
padding: 0;
}

.tagItem {
display: flex;
align-items: center;

font-size: 2rem;

img {
background: var(--mdc-theme-secondary-dark);
border-radius: 50%;
padding: 4px;
margin-right: 1rem;
cursor: pointer;
}
}

0 comments on commit 64ae92c

Please sign in to comment.