Skip to content

Commit 15d2e0f

Browse files
committed
implement "remove tags" from accounts
1 parent 40ed981 commit 15d2e0f

File tree

2 files changed

+56
-16
lines changed

2 files changed

+56
-16
lines changed

src/packages/frontend/frame-editors/crm-editor/views/view-menu/tag-accounts.tsx

Lines changed: 55 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
11
import { useState } from "react";
2-
import { Alert, Button, Input, Modal, Progress, Space, Spin } from "antd";
2+
import {
3+
Alert,
4+
Button,
5+
Input,
6+
Modal,
7+
Progress,
8+
Space,
9+
Spin,
10+
Switch,
11+
} from "antd";
312
import { Icon } from "@cocalc/frontend/components/icon";
413
import { webapp_client } from "@cocalc/frontend/webapp-client";
514
import type { ColumnsType } from "../../fields";
6-
import { Set } from "immutable";
15+
import { Set as iSet } from "immutable";
716
import { plural } from "@cocalc/util/misc";
817
import ShowError from "@cocalc/frontend/components/error";
918
import { map as awaitMap } from "awaiting";
@@ -12,7 +21,7 @@ const MAX_PARALLEL_TASKS = 15;
1221
interface Props {
1322
title: string;
1423
onClose: () => void;
15-
selected: Set<any> | undefined;
24+
selected: iSet<string> | undefined;
1625
data: { account_id: string; tags?: string[] }[];
1726
primaryKey: string;
1827
columns: ColumnsType[];
@@ -33,17 +42,18 @@ export default function TagAccounts({
3342
const [loading, setLoading] = useState<boolean>(false);
3443
const [progress, setProgress] = useState<number>(0);
3544
const [error, setError] = useState<string>("");
45+
const [add, setAdd] = useState<boolean>(true);
3646

3747
if (selected == null) {
3848
return null;
3949
}
4050

4151
const save = async () => {
42-
const tags = value
52+
const tags0 = value
4353
.split(",")
4454
.map((x) => x.trim())
4555
.filter((x) => !!x);
46-
if (tags.length == 0 || selected == null || selected.size == 0) {
56+
if (tags0.length == 0 || selected == null || selected.size == 0) {
4757
setValue("");
4858
return;
4959
}
@@ -57,21 +67,42 @@ export default function TagAccounts({
5767
setLoading(true);
5868
let done = 0;
5969
let goal = selected.size;
70+
const check = () => {
71+
done += 1;
72+
setProgress(Math.round((done * 100) / goal));
73+
};
74+
6075
const task = async (account_id) => {
76+
let tags;
77+
if (add) {
78+
tags = Array.from(
79+
new Set(tagsByAccount[account_id].concat(tags0)),
80+
).sort();
81+
} else {
82+
const x = new Set(tagsByAccount[account_id]);
83+
const n = x.size;
84+
for (const tag of tags0) {
85+
x.delete(tag);
86+
}
87+
if (x.size == n) {
88+
check();
89+
return;
90+
}
91+
tags = Array.from(x).sort();
92+
}
6193
try {
6294
await webapp_client.async_query({
6395
query: {
6496
crm_accounts: {
6597
account_id,
66-
tags: tagsByAccount[account_id].concat(tags),
98+
tags,
6799
},
68100
},
69101
});
70102
} catch (err) {
71103
errors.push(`${err}`);
72104
}
73-
done += 1;
74-
setProgress(Math.round((done * 100) / goal));
105+
check();
75106
};
76107
await awaitMap(Array.from(selected), MAX_PARALLEL_TASKS, task);
77108
setValue("");
@@ -94,8 +125,15 @@ export default function TagAccounts({
94125
footer={null}
95126
title={
96127
<div style={{ margin: "0 15px" }}>
97-
<Icon name="tags-outlined" /> Tag {selected.size} Selected{" "}
98-
{plural(selected.size, "Account")}
128+
<Icon name="tags-outlined" /> {add ? "Tag" : "Untag"} {selected.size}{" "}
129+
Selected {plural(selected.size, "Account")}
130+
<Switch
131+
style={{ float: "right", marginRight: "30px" }}
132+
checkedChildren="Add"
133+
unCheckedChildren="Remove"
134+
defaultChecked
135+
onChange={setAdd}
136+
/>
99137
</div>
100138
}
101139
onCancel={onClose}
@@ -107,24 +145,26 @@ export default function TagAccounts({
107145
value={value}
108146
onChange={(e) => setValue(e.target.value)}
109147
placeholder="Tag or tag1,tag2,..."
110-
size="large"
111148
/>
112149
<Button
113-
size="large"
114-
style={{ height: "41px" /* hack around antd bug?*/ }}
150+
style={{ height: "37px" /* hack around antd bug?*/ }}
115151
disabled={!value.trim() || loading}
116152
onClick={() => {
117153
save();
118154
}}
119155
>
120-
Tag {plural(selected.size, "Account")} {loading && <Spin />}
156+
{!add ? "Untag" : "Tag"} {plural(selected.size, "Account")}{" "}
157+
{loading && <Spin />}
121158
</Button>
122159
</Space.Compact>
123160
<Alert
124161
style={{ margin: "15px 0" }}
125162
type="info"
126163
message={
127-
<>The above tags will be applied to each selected account.</>
164+
<>
165+
The above tags will be {add ? "added to" : "removed from"} each
166+
selected account.
167+
</>
128168
}
129169
/>
130170
{loading && (

src/packages/frontend/frame-editors/crm-editor/views/view-menu/top.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ export default function TopMenu({
141141
},
142142
];
143143
if (dbtable == "crm_accounts") {
144-
items[0].children.push({
144+
items[0].children.unshift({
145145
type: "group",
146146
label: (
147147
<Divider>

0 commit comments

Comments
 (0)