feat: handle tag overflow

This commit is contained in:
Akuoko Daniel Jnr 2021-03-30 17:36:26 +00:00
parent 7d769f6e41
commit 1adad7d273
No known key found for this signature in database
GPG Key ID: 1C95803CACD3E9DC
2 changed files with 108 additions and 64 deletions

View File

@ -19,6 +19,7 @@ import { GroupSelectable, Selectable } from "~/components/core/Selectable/";
import SlateMediaObjectPreview from "~/components/core/SlateMediaObjectPreview";
import FilePreviewBubble from "~/components/core/FilePreviewBubble";
import isEqual from "lodash/isEqual";
const STYLES_CONTAINER_HOVER = css`
display: flex;
@ -233,6 +234,70 @@ const STYLES_TAG = css`
}
`;
class Tags extends React.Component {
state = {
isTruncated: false,
truncateIndex: 0,
};
listWrapper = React.createRef();
listEl = React.createRef();
componentDidMount() {
this._handleTruncate();
}
componentDidUpdate(prevProps, prevState) {
if (!isEqual(prevProps.tags, this.props.tags)) {
this._handleTruncate();
}
}
_handleTruncate = () => {
const listWrapper = this.listWrapper.current?.getBoundingClientRect();
const tagNodes = this.listEl.current?.querySelectorAll("li");
const tagElems = Array.from(tagNodes);
let total = 0;
const truncateIndex = tagElems.findIndex((tagElem) => {
const { width } = tagElem?.getBoundingClientRect();
total += width;
if (total >= listWrapper.width - 50) {
return true;
}
});
if (truncateIndex > 0) {
this.setState({ isTruncated: true, truncateIndex });
return;
}
this.setState({ isTruncated: false, truncateIndex: tagElems.length });
};
render() {
const { tags } = this.props;
return (
<div css={STYLES_TAGS_WRAPPER}>
<div ref={this.listWrapper} style={{ width: 340 }}>
<ul css={STYLES_LIST} ref={this.listEl}>
{(this.state.isTruncated ? tags.slice(0, this.state.truncateIndex) : tags).map(
(tag) => (
<li key={tag} css={STYLES_TAG}>
<span>{tag}</span>
</li>
)
)}
</ul>
{this.state.isTruncated && <span>...</span>}
</div>
</div>
);
}
}
export default class DataView extends React.Component {
_mounted = false;
@ -514,27 +579,6 @@ export default class DataView extends React.Component {
e.dataTransfer.setData("DownloadURL", `${type}:${title}:${url}`);
};
_checkTagsOverflow = (i) => {
let nodes = document.querySelectorAll(`[data-tag-list="${i}"]`)[0]?.childNodes;
if (nodes) {
let items = Array.from(nodes);
let total = 0;
let sliceIndex;
for (let [index, item] of Object.entries(items)) {
if (total >= 220) {
sliceIndex = index;
break;
}
total += item.offsetWidth;
}
return sliceIndex;
}
};
getCommonTagFromSelectedItems = () => {
const { items } = this.props;
const { checked } = this.state;
@ -634,7 +678,7 @@ export default class DataView extends React.Component {
});
}}
>
Edit tags
Edit tag{numChecked > 1 ? "s" : ""}
</ButtonPrimary>
<ButtonWarning
transparent
@ -845,7 +889,7 @@ export default class DataView extends React.Component {
{
key: "tags",
name: <div style={{ fontSize: "0.9rem", padding: "18px 0" }}>Tags</div>,
width: "341px",
width: "360px",
},
{
key: "size",
@ -900,21 +944,7 @@ export default class DataView extends React.Component {
</FilePreviewBubble>
</Selectable>
),
tags: (
<>
{each.tags && (
<div css={STYLES_TAGS_WRAPPER}>
<ul css={STYLES_LIST} data-tag-list={index}>
{each.tags.map((tag, i) => (
<li key={tag} css={STYLES_TAG}>
<span>{tag}</span>
</li>
))}
</ul>
</div>
)}
</>
),
tags: <>{each.tags && <Tags tags={each.tags} />}</>,
size: <div css={STYLES_VALUE}>{Strings.bytesToSize(each.size)}</div>,
more: (
<div

View File

@ -20,7 +20,7 @@ const STYLES_GROUPING = css`
export default class SidebarEditTags extends React.Component {
state = {
newTags:
tags:
!Array.isArray(this.props.sidebarData.commonTags) ||
this.props.sidebarData.commonTags?.length === 0
? []
@ -38,10 +38,10 @@ export default class SidebarEditTags extends React.Component {
});
};
/* updateSuggestions = () => {
let newSuggestions = new Set([...this.props.sidebarData.suggestions, ...this.state.newTags]);
updateSuggestions = () => {
let newSuggestions = new Set([...this.props.sidebarData.suggestions, ...this.state.tags]);
this.setState({ suggestions: Array.from(newSuggestions) });
}; */
};
_handleSave = async (details, index) => {
let { objects } = this.props.sidebarData;
@ -51,40 +51,55 @@ export default class SidebarEditTags extends React.Component {
id: this.props.viewer.id,
data: objects[index],
});
console.log(response);
this.props.onUpdateViewer({ tags: this.state.suggestions });
Events.hasError(response);
};
_handleSubmit = async () => {
let { checked, objects, commonTags } = this.props.sidebarData;
this.props.onCancel();
let { checked, objects, commonTags } = this.props.sidebarData;
const checkedIndexes = Object.keys(checked);
/* data must be fixed */
/* let data = { tags: this.state.newTags }; */
let data;
await Promise.all(
checkedIndexes.map(async (checkedIndex) => {
let prevTags = objects[checkedIndex]?.tags;
console.log({ prevTags });
let newTags = this.state.newTags;
console.log({ newTags });
console.log({ commonTags });
/* commonTags */
let objectTags = Array.isArray(objects[checkedIndex]?.tags)
? objects[checkedIndex].tags
: [];
let newTags = this.state.tags;
/*
1. If there is an item in newTags which is not in commonTag, add to prevTags;
2. If there is an item in commonTag which is not in newTags, remove it from prevTags;
*/
let data;
if (newTags.length > commonTags.length) {
let update = new Set([...prevTags, ...newTags, ...commonTags]);
data = { tags: Array.from(update) };
/* NOTE(daniel): since there are no common tags, we are simply adding new tags to the files */
if (!commonTags.length) {
data = { tags: [...new Set([...objectTags, ...newTags])] };
return await this._handleSave(data, checkedIndex);
}
this._handleSave(data, checkedIndex);
/* NOTE(daniel): symmetrical difference between new tags and common tags */
let diff = newTags
.filter((i) => !commonTags.includes(i))
.concat(commonTags.filter((i) => !newTags.includes(i)));
let update = diff.reduce((acc, cur) => {
if (!commonTags.includes(cur) && newTags.includes(cur)) {
acc.push(cur);
} else if (commonTags.includes(cur) && !newTags.includes(cur)) {
let removalIndex = acc.findIndex((item) => item === cur);
acc.splice(removalIndex, 1);
}
return acc;
}, objectTags);
data = { tags: update };
return await this._handleSave(data, checkedIndex);
})
);
this.updateSuggestions();
};
render() {
@ -125,9 +140,8 @@ export default class SidebarEditTags extends React.Component {
<Tag
name="tags"
placeholder={`Edit tags for ${`${numChecked} file${numChecked === 1 ? "" : "s"}`} `}
tags={this.state.newTags}
tags={this.state.tags}
suggestions={this.state.suggestions}
style={{ margin: "0 0 16px" }}
onChange={this._handleChange}
/* handleTagDelete={this._handleTagDelete} */
/>