From 684e0159e1c1a630dd163e25aba33cf76728c697 Mon Sep 17 00:00:00 2001 From: imbeacon Date: Wed, 7 Jun 2023 08:11:19 +0300 Subject: [PATCH 01/22] Added unassign for alarms on user removal --- .../entitiy/alarm/DefaultTbAlarmService.java | 43 +++++++++++++++++++ .../service/entitiy/alarm/TbAlarmService.java | 3 ++ .../entitiy/user/DefaultUserService.java | 3 ++ 3 files changed, 49 insertions(+) diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java index caf65d39ec..141917f11f 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java @@ -29,6 +29,7 @@ import org.thingsboard.server.common.data.alarm.AlarmComment; import org.thingsboard.server.common.data.alarm.AlarmCommentType; import org.thingsboard.server.common.data.alarm.AlarmCreateOrUpdateActiveRequest; import org.thingsboard.server.common.data.alarm.AlarmInfo; +import org.thingsboard.server.common.data.alarm.AlarmQueryV2; import org.thingsboard.server.common.data.alarm.AlarmUpdateRequest; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; @@ -36,9 +37,13 @@ import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; +import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.service.entitiy.AbstractTbEntityService; import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; @Service @AllArgsConstructor @@ -210,6 +215,44 @@ public class DefaultTbAlarmService extends AbstractTbEntityService implements Tb return alarmInfo; } + @Override + public void unassignUserAlarms(TenantId tenantId, User user, long unassignTs) throws ThingsboardException { + AlarmQueryV2 alarmQuery = AlarmQueryV2.builder().assigneeId(user.getId()).pageLink(new TimePageLink(Integer.MAX_VALUE)).build(); + try { + List alarms = alarmService.findAlarmsV2(tenantId, alarmQuery).get(30, TimeUnit.SECONDS).getData(); + if (alarms.isEmpty()) { + throw new ThingsboardException(ThingsboardErrorCode.ITEM_NOT_FOUND); + } + for (AlarmInfo alarm : alarms) { + AlarmApiCallResult result = alarmSubscriptionService.unassignAlarm(tenantId, alarm.getId(), getOrDefault(unassignTs)); + if (!result.isSuccessful()) { + continue; + } + if (result.isModified()) { + AlarmComment alarmComment = AlarmComment.builder() + .alarmId(alarm.getId()) + .type(AlarmCommentType.SYSTEM) + .comment(JacksonUtil.newObjectNode().put("text", String.format("Alarm was unassigned because user %s - was deleted", + (user.getFirstName() == null || user.getLastName() == null) ? user.getName() : user.getFirstName() + " " + user.getLastName())) + .put("userId", user.getId().toString()) + .put("subtype", "ASSIGN")) + .build(); + try { + alarmCommentService.saveAlarmComment(alarm, alarmComment, user); + } catch (ThingsboardException e) { + log.error("Failed to save alarm comment", e); + } + notificationEntityService.notifyCreateOrUpdateAlarm(result.getAlarm(), ActionType.ALARM_UNASSIGNED, user); + } else { + throw new ThingsboardException("Alarm was already unassigned!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); + } + } + + } catch (InterruptedException | ExecutionException | TimeoutException e) { + throw new RuntimeException(e); + } + } + @Override public Boolean delete(Alarm alarm, User user) { TenantId tenantId = alarm.getTenantId(); diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmService.java index a2ae9c8cc7..ed4af5d1bd 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmService.java @@ -19,6 +19,7 @@ import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; public interface TbAlarmService { @@ -37,5 +38,7 @@ public interface TbAlarmService { AlarmInfo unassign(Alarm alarm, long unassignTs, User user) throws ThingsboardException; + void unassignUserAlarms(TenantId tenantId, User user, long unassignTs) throws ThingsboardException; + Boolean delete(Alarm alarm, User user); } diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/user/DefaultUserService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/user/DefaultUserService.java index c83c48cc8a..0c04e46ff5 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/user/DefaultUserService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/user/DefaultUserService.java @@ -30,6 +30,7 @@ import org.thingsboard.server.common.data.security.UserCredentials; import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.entitiy.AbstractTbEntityService; +import org.thingsboard.server.service.entitiy.alarm.TbAlarmService; import org.thingsboard.server.service.security.system.SystemSecurityService; import javax.servlet.http.HttpServletRequest; @@ -43,6 +44,7 @@ import static org.thingsboard.server.controller.UserController.ACTIVATE_URL_PATT public class DefaultUserService extends AbstractTbEntityService implements TbUserService { private final UserService userService; + private final TbAlarmService tbAlarmService; private final MailService mailService; private final SystemSecurityService systemSecurityService; @@ -80,6 +82,7 @@ public class DefaultUserService extends AbstractTbEntityService implements TbUse UserId userId = tbUser.getId(); try { + tbAlarmService.unassignUserAlarms(tenantId, tbUser, System.currentTimeMillis()); userService.deleteUser(tenantId, userId); notificationEntityService.notifyCreateOrUpdateOrDelete(tenantId, customerId, userId, tbUser, user, ActionType.DELETED, true, null, customerId.toString()); From 11f897d9b126e60e4693d1c0615963fadf7c6b26 Mon Sep 17 00:00:00 2001 From: imbeacon Date: Wed, 7 Jun 2023 10:03:17 +0300 Subject: [PATCH 02/22] Added test --- .../controller/AlarmControllerTest.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java index 05030f0091..c6b31ce683 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java @@ -32,6 +32,7 @@ import org.springframework.test.context.ContextConfiguration; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.alarm.AlarmSeverity; @@ -39,6 +40,7 @@ import org.thingsboard.server.common.data.alarm.AlarmStatus; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.page.PageData; +import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.dao.alarm.AlarmDao; import org.thingsboard.server.dao.service.DaoSqlTest; @@ -529,6 +531,41 @@ public class AlarmControllerTest extends AbstractControllerTest { tenantId, customerId, customerUserId, CUSTOMER_USER_EMAIL, ActionType.ALARM_UNASSIGNED); } + @Test + public void testUnassignAlarmOnUserRemoving() throws Exception { + loginTenantAdmin(); + + + User user = new User(); + user.setAuthority(Authority.TENANT_ADMIN); + user.setTenantId(tenantId); + user.setEmail("tenantForAssign@thingsboard.org"); + User savedUser = createUser(user, "password"); + + Alarm alarm = createAlarm(TEST_ALARM_TYPE); + Mockito.reset(tbClusterService, auditLogService); + long beforeAssignmentTs = System.currentTimeMillis(); + Thread.sleep(2); + + doPost("/api/alarm/" + alarm.getId() + "/assign/" + savedUser.getId().getId()).andExpect(status().isOk()); + AlarmInfo foundAlarm = doGet("/api/alarm/info/" + alarm.getId(), AlarmInfo.class); + Assert.assertNotNull(foundAlarm); + Assert.assertEquals(savedUser.getId(), foundAlarm.getAssigneeId()); + Assert.assertTrue(foundAlarm.getAssignTs() > beforeAssignmentTs && foundAlarm.getAssignTs() < System.currentTimeMillis()); + + beforeAssignmentTs = System.currentTimeMillis(); + + Mockito.reset(tbClusterService, auditLogService); + + doDelete("/api/user/" + savedUser.getId().getId()).andExpect(status().isOk()); + Thread.sleep(2); + + foundAlarm = doGet("/api/alarm/info/" + alarm.getId(), AlarmInfo.class); + Assert.assertNotNull(foundAlarm); + Assert.assertNull(foundAlarm.getAssigneeId()); + Assert.assertTrue(foundAlarm.getAssignTs() > beforeAssignmentTs && foundAlarm.getAssignTs() < System.currentTimeMillis()); + } + @Test public void testFindAlarmsViaCustomerUser() throws Exception { loginCustomerUser(); From 505acb560f17beb2f74c7b922c8fa840ea6d5df1 Mon Sep 17 00:00:00 2001 From: imbeacon Date: Fri, 9 Jun 2023 10:22:00 +0300 Subject: [PATCH 03/22] Removed exception throw on alarms not found for user on deleting --- .../server/service/entitiy/alarm/DefaultTbAlarmService.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java index 141917f11f..fc3198a736 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java @@ -220,9 +220,6 @@ public class DefaultTbAlarmService extends AbstractTbEntityService implements Tb AlarmQueryV2 alarmQuery = AlarmQueryV2.builder().assigneeId(user.getId()).pageLink(new TimePageLink(Integer.MAX_VALUE)).build(); try { List alarms = alarmService.findAlarmsV2(tenantId, alarmQuery).get(30, TimeUnit.SECONDS).getData(); - if (alarms.isEmpty()) { - throw new ThingsboardException(ThingsboardErrorCode.ITEM_NOT_FOUND); - } for (AlarmInfo alarm : alarms) { AlarmApiCallResult result = alarmSubscriptionService.unassignAlarm(tenantId, alarm.getId(), getOrDefault(unassignTs)); if (!result.isSuccessful()) { From 5ddb62322ccab6a147d88c8f59d4d5cf68251c78 Mon Sep 17 00:00:00 2001 From: imbeacon Date: Fri, 9 Jun 2023 13:47:51 +0300 Subject: [PATCH 04/22] Updated test --- .../thingsboard/server/controller/AlarmControllerTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java index c6b31ce683..f83deaad2e 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java @@ -551,7 +551,7 @@ public class AlarmControllerTest extends AbstractControllerTest { AlarmInfo foundAlarm = doGet("/api/alarm/info/" + alarm.getId(), AlarmInfo.class); Assert.assertNotNull(foundAlarm); Assert.assertEquals(savedUser.getId(), foundAlarm.getAssigneeId()); - Assert.assertTrue(foundAlarm.getAssignTs() > beforeAssignmentTs && foundAlarm.getAssignTs() < System.currentTimeMillis()); + Assert.assertTrue(foundAlarm.getAssignTs() > beforeAssignmentTs); beforeAssignmentTs = System.currentTimeMillis(); @@ -563,7 +563,7 @@ public class AlarmControllerTest extends AbstractControllerTest { foundAlarm = doGet("/api/alarm/info/" + alarm.getId(), AlarmInfo.class); Assert.assertNotNull(foundAlarm); Assert.assertNull(foundAlarm.getAssigneeId()); - Assert.assertTrue(foundAlarm.getAssignTs() > beforeAssignmentTs && foundAlarm.getAssignTs() < System.currentTimeMillis()); + Assert.assertTrue(foundAlarm.getAssignTs() > beforeAssignmentTs); } @Test From b33c39dd253215aec3652ddcf955d8ce78158361 Mon Sep 17 00:00:00 2001 From: imbeacon Date: Thu, 15 Jun 2023 11:58:48 +0300 Subject: [PATCH 05/22] Refactoring --- .../org/thingsboard/server/controller/AlarmControllerTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java index f83deaad2e..dccb650555 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java @@ -535,7 +535,6 @@ public class AlarmControllerTest extends AbstractControllerTest { public void testUnassignAlarmOnUserRemoving() throws Exception { loginTenantAdmin(); - User user = new User(); user.setAuthority(Authority.TENANT_ADMIN); user.setTenantId(tenantId); From 7e5069d78452ee48217bbeb22d08476e0ba7ff59 Mon Sep 17 00:00:00 2001 From: imbeacon Date: Fri, 16 Jun 2023 09:26:19 +0300 Subject: [PATCH 06/22] Changed test to work with different tenant, to avoid affecting by other tests --- .../server/controller/AlarmControllerTest.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java index dccb650555..c2e34c5d2e 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java @@ -533,7 +533,7 @@ public class AlarmControllerTest extends AbstractControllerTest { @Test public void testUnassignAlarmOnUserRemoving() throws Exception { - loginTenantAdmin(); + loginDifferentTenant(); User user = new User(); user.setAuthority(Authority.TENANT_ADMIN); @@ -541,7 +541,20 @@ public class AlarmControllerTest extends AbstractControllerTest { user.setEmail("tenantForAssign@thingsboard.org"); User savedUser = createUser(user, "password"); - Alarm alarm = createAlarm(TEST_ALARM_TYPE); + Device device = createDevice("Different tenant device", "default", "differentTenantTest"); + + Alarm alarm = Alarm.builder() + .type(TEST_ALARM_TYPE) + .tenantId(differentTenantId) + .originator(device.getId()) + .severity(AlarmSeverity.MAJOR) + .build(); + alarm = doPost("/api/alarm", alarm, Alarm.class); + Assert.assertNotNull(alarm); + + alarm = doGet("/api/alarm/info/" + alarm.getId(), AlarmInfo.class); + Assert.assertNotNull(alarm); + Mockito.reset(tbClusterService, auditLogService); long beforeAssignmentTs = System.currentTimeMillis(); Thread.sleep(2); From b8e12a46217e6359250b645b33b364d54c39d0a3 Mon Sep 17 00:00:00 2001 From: imbeacon Date: Fri, 16 Jun 2023 10:38:55 +0300 Subject: [PATCH 07/22] Refactoring --- .../server/service/entitiy/alarm/DefaultTbAlarmService.java | 4 +--- .../server/service/entitiy/alarm/TbAlarmService.java | 2 +- .../thingsboard/server/controller/AlarmControllerTest.java | 6 ++---- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java index fc3198a736..07c66e359a 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java @@ -216,7 +216,7 @@ public class DefaultTbAlarmService extends AbstractTbEntityService implements Tb } @Override - public void unassignUserAlarms(TenantId tenantId, User user, long unassignTs) throws ThingsboardException { + public void unassignUserAlarms(TenantId tenantId, User user, long unassignTs) { AlarmQueryV2 alarmQuery = AlarmQueryV2.builder().assigneeId(user.getId()).pageLink(new TimePageLink(Integer.MAX_VALUE)).build(); try { List alarms = alarmService.findAlarmsV2(tenantId, alarmQuery).get(30, TimeUnit.SECONDS).getData(); @@ -240,8 +240,6 @@ public class DefaultTbAlarmService extends AbstractTbEntityService implements Tb log.error("Failed to save alarm comment", e); } notificationEntityService.notifyCreateOrUpdateAlarm(result.getAlarm(), ActionType.ALARM_UNASSIGNED, user); - } else { - throw new ThingsboardException("Alarm was already unassigned!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); } } diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmService.java index ed4af5d1bd..24af185539 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmService.java @@ -38,7 +38,7 @@ public interface TbAlarmService { AlarmInfo unassign(Alarm alarm, long unassignTs, User user) throws ThingsboardException; - void unassignUserAlarms(TenantId tenantId, User user, long unassignTs) throws ThingsboardException; + void unassignUserAlarms(TenantId tenantId, User user, long unassignTs); Boolean delete(Alarm alarm, User user); } diff --git a/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java index c2e34c5d2e..8f28ca0110 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java @@ -557,25 +557,23 @@ public class AlarmControllerTest extends AbstractControllerTest { Mockito.reset(tbClusterService, auditLogService); long beforeAssignmentTs = System.currentTimeMillis(); - Thread.sleep(2); doPost("/api/alarm/" + alarm.getId() + "/assign/" + savedUser.getId().getId()).andExpect(status().isOk()); AlarmInfo foundAlarm = doGet("/api/alarm/info/" + alarm.getId(), AlarmInfo.class); Assert.assertNotNull(foundAlarm); Assert.assertEquals(savedUser.getId(), foundAlarm.getAssigneeId()); - Assert.assertTrue(foundAlarm.getAssignTs() > beforeAssignmentTs); + Assert.assertTrue(foundAlarm.getAssignTs() >= beforeAssignmentTs); beforeAssignmentTs = System.currentTimeMillis(); Mockito.reset(tbClusterService, auditLogService); doDelete("/api/user/" + savedUser.getId().getId()).andExpect(status().isOk()); - Thread.sleep(2); foundAlarm = doGet("/api/alarm/info/" + alarm.getId(), AlarmInfo.class); Assert.assertNotNull(foundAlarm); Assert.assertNull(foundAlarm.getAssigneeId()); - Assert.assertTrue(foundAlarm.getAssignTs() > beforeAssignmentTs); + Assert.assertTrue(foundAlarm.getAssignTs() >= beforeAssignmentTs); } @Test From ce103cf3396614c5a151c9bfd74c23e4fcbade05 Mon Sep 17 00:00:00 2001 From: imbeacon Date: Mon, 19 Jun 2023 07:27:44 +0300 Subject: [PATCH 08/22] changed test to get id of savedDifferentTenant --- .../org/thingsboard/server/controller/AlarmControllerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java index 8f28ca0110..50761be096 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java @@ -545,7 +545,7 @@ public class AlarmControllerTest extends AbstractControllerTest { Alarm alarm = Alarm.builder() .type(TEST_ALARM_TYPE) - .tenantId(differentTenantId) + .tenantId(savedDifferentTenant.getId()) .originator(device.getId()) .severity(AlarmSeverity.MAJOR) .build(); From 95878afcfb22102d3c90db196a40739662869176 Mon Sep 17 00:00:00 2001 From: rusikv Date: Tue, 27 Jun 2023 17:30:56 +0300 Subject: [PATCH 09/22] Test rule node script function with selected event implementation --- .../script/node-script-test.service.ts | 52 ++++++++----------- .../components/details-panel.component.ts | 10 +++- .../components/event/event-table-config.ts | 26 ++++++++-- .../components/event/event-table.component.ts | 34 ++++++++++-- .../rulechain/rule-node-config.component.ts | 8 +++ .../rule-node-details.component.html | 3 +- .../rulechain/rule-node-details.component.ts | 4 ++ .../rulechain/rulechain-page.component.html | 13 +++-- .../rulechain/rulechain-page.component.ts | 16 +++++- .../src/app/shared/models/rule-node.models.ts | 35 ++++++++++--- .../assets/locale/locale.constant-en_US.json | 11 +++- 11 files changed, 160 insertions(+), 52 deletions(-) diff --git a/ui-ngx/src/app/core/services/script/node-script-test.service.ts b/ui-ngx/src/app/core/services/script/node-script-test.service.ts index 1a33275111..c3e0da73ad 100644 --- a/ui-ngx/src/app/core/services/script/node-script-test.service.ts +++ b/ui-ngx/src/app/core/services/script/node-script-test.service.ts @@ -23,8 +23,8 @@ import { NodeScriptTestDialogComponent, NodeScriptTestDialogData } from '@shared/components/dialog/node-script-test-dialog.component'; -import { sortObjectKeys } from '@core/utils'; import { ScriptLanguage } from '@shared/models/rule-node.models'; +import { DebugRuleNodeEventBody } from '@shared/models/event.models'; @Injectable({ providedIn: 'root' @@ -37,56 +37,50 @@ export class NodeScriptTestService { testNodeScript(script: string, scriptType: string, functionTitle: string, functionName: string, argNames: string[], ruleNodeId: string, helpId?: string, - scriptLang?: ScriptLanguage): Observable { - if (ruleNodeId) { + scriptLang?: ScriptLanguage, debugEventBody?: DebugRuleNodeEventBody): Observable { + if (ruleNodeId && !debugEventBody) { return this.ruleChainService.getLatestRuleNodeDebugInput(ruleNodeId).pipe( switchMap((debugIn) => { - let msg: any; - let metadata: {[key: string]: string}; - let msgType: string; - if (debugIn) { - if (debugIn.data) { - try { - msg = JSON.parse(debugIn.data); - } catch (e) {} - } - if (debugIn.metadata) { - try { - metadata = JSON.parse(debugIn.metadata); - } catch (e) {} - } - msgType = debugIn.msgType; - } return this.openTestScriptDialog(script, scriptType, functionTitle, - functionName, argNames, msg, metadata, msgType, helpId, scriptLang); + functionName, argNames, debugIn, helpId, scriptLang); }) ); } else { return this.openTestScriptDialog(script, scriptType, functionTitle, - functionName, argNames, null, null, null, helpId, scriptLang); + functionName, argNames, debugEventBody, helpId, scriptLang); } } - private openTestScriptDialog(script: string, scriptType: string, - functionTitle: string, functionName: string, argNames: string[], - msg?: any, metadata?: {[key: string]: string}, msgType?: string, helpId?: string, + private openTestScriptDialog(script: string, scriptType: string, functionTitle: string, functionName: string, + argNames: string[], eventBody: DebugRuleNodeEventBody, helpId?: string, scriptLang?: ScriptLanguage): Observable { - if (!msg) { + let msg: any; + let metadata: {[key: string]: string}; + let msgType: string; + if (eventBody && eventBody.data) { + try { + msg = JSON.parse(eventBody.data); + } catch (e) {} + } else { msg = { temperature: 22.4, humidity: 78 }; } - if (!metadata) { + if (eventBody && eventBody.metadata) { + try { + metadata = JSON.parse(eventBody.metadata); + } catch (e) {} + } else { metadata = { deviceName: 'Test Device', deviceType: 'default', ts: new Date().getTime() + '' }; - } else { - metadata = sortObjectKeys(metadata); } - if (!msgType) { + if (eventBody && eventBody.msgType) { + msgType = eventBody.msgType; + } else { msgType = 'POST_TELEMETRY_REQUEST'; } return this.dialog.open(NodeScriptTestDialogComponent, diff --git a/ui-ngx/src/app/modules/home/components/details-panel.component.ts b/ui-ngx/src/app/modules/home/components/details-panel.component.ts index b2f8a059f3..ac8d6e3bc3 100644 --- a/ui-ngx/src/app/modules/home/components/details-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/details-panel.component.ts @@ -15,7 +15,6 @@ /// import { - ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, @@ -56,7 +55,12 @@ export class DetailsPanelComponent extends PageComponent implements OnDestroy { } this.theFormValue = value; if (this.theFormValue !== null) { - this.formSubscription = this.theFormValue.valueChanges.subscribe(() => this.cd.detectChanges()); + this.formSubscription = this.theFormValue.valueChanges.subscribe(() => { + if (this.isReadOnly) { + this.switchToFirstTab.emit(); + } + this.cd.detectChanges() + }); } } } @@ -73,6 +77,8 @@ export class DetailsPanelComponent extends PageComponent implements OnDestroy { applyDetails = new EventEmitter(); @Output() closeSearch = new EventEmitter(); + @Output() + switchToFirstTab = new EventEmitter() isEditValue = false; showSearchPane = false; diff --git a/ui-ngx/src/app/modules/home/components/event/event-table-config.ts b/ui-ngx/src/app/modules/home/components/event/event-table-config.ts index a9816a130c..51bd99fde0 100644 --- a/ui-ngx/src/app/modules/home/components/event/event-table-config.ts +++ b/ui-ngx/src/app/modules/home/components/event/event-table-config.ts @@ -21,7 +21,7 @@ import { EntityTableColumn, EntityTableConfig } from '@home/models/entity/entities-table-config.models'; -import { DebugEventType, Event, EventType, FilterEventBody } from '@shared/models/event.models'; +import { DebugEventType, DebugRuleNodeEventBody, Event, EventType, FilterEventBody } from '@shared/models/event.models'; import { TimePageLink } from '@shared/models/page/page-link'; import { TranslateService } from '@ngx-translate/core'; import { DatePipe } from '@angular/common'; @@ -30,7 +30,7 @@ import { EntityId } from '@shared/models/id/entity-id'; import { EventService } from '@app/core/http/event.service'; import { EventTableHeaderComponent } from '@home/components/event/event-table-header.component'; import { EntityTypeResource } from '@shared/models/entity-type.models'; -import { Observable } from 'rxjs'; +import { BehaviorSubject, Observable } from 'rxjs'; import { PageData } from '@shared/models/page/page-data'; import { Direction } from '@shared/models/page/sort-order'; import { DialogService } from '@core/services/dialog.service'; @@ -49,6 +49,8 @@ import { EventFilterPanelData, FilterEntityColumn } from '@home/components/event/event-filter-panel.component'; +import { NodeScriptTestService } from '@core/services/script/node-script-test.service'; +import { ruleNodeClazzFunctionNameTranslations } from '@shared/models/rule-node.models'; export class EventTableConfig extends EntityTableConfig { @@ -72,6 +74,8 @@ export class EventTableConfig extends EntityTableConfig { eventTypes: Array; + debugEventSelectedSubject = new BehaviorSubject(null); + constructor(private eventService: EventService, private dialogService: DialogService, private translate: TranslateService, @@ -84,7 +88,11 @@ export class EventTableConfig extends EntityTableConfig { private debugEventTypes: Array = null, private overlay: Overlay, private viewContainerRef: ViewContainerRef, - private cd: ChangeDetectorRef) { + private cd: ChangeDetectorRef, + private nodeScriptTestService: NodeScriptTestService, + private isRuleNodeDebugModeEnabled: boolean, + private editingRuleNodeHasScript: boolean, + private rulenodeClazz: string) { super(); this.loadDataOnInit = false; this.tableTitle = ''; @@ -317,6 +325,18 @@ export class EventTableConfig extends EntityTableConfig { onAction: ($event, entity) => this.showContent($event, entity.body.error, 'event.error') }, + '48px'), + new EntityActionTableColumn('test', '', + { + name: this.translate.instant('rulenode.test-function', + {function: this.translate.instant(ruleNodeClazzFunctionNameTranslations[this.rulenodeClazz])}), + icon: 'bug_report', + isEnabled: (entity) => this.isRuleNodeDebugModeEnabled && entity.body.type === 'IN' && + this.editingRuleNodeHasScript, + onAction: ($event, entity) => { + this.debugEventSelectedSubject.next(entity.body); + } + }, '48px') ); break; diff --git a/ui-ngx/src/app/modules/home/components/event/event-table.component.ts b/ui-ngx/src/app/modules/home/components/event/event-table.component.ts index fbdd0a07da..4781b4811d 100644 --- a/ui-ngx/src/app/modules/home/components/event/event-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/event/event-table.component.ts @@ -17,10 +17,10 @@ import { AfterViewInit, ChangeDetectorRef, - Component, + Component, EventEmitter, Input, OnDestroy, - OnInit, + OnInit, Output, ViewChild, ViewContainerRef } from '@angular/core'; @@ -32,9 +32,10 @@ import { EntitiesTableComponent } from '@home/components/entity/entities-table.c import { EventTableConfig } from './event-table-config'; import { EventService } from '@core/http/event.service'; import { DialogService } from '@core/services/dialog.service'; -import { DebugEventType, EventType } from '@shared/models/event.models'; +import { DebugEventType, DebugRuleNodeEventBody, EventType } from '@shared/models/event.models'; import { Overlay } from '@angular/cdk/overlay'; import { Subscription } from 'rxjs'; +import { NodeScriptTestService } from '@core/services/script/node-script-test.service'; @Component({ selector: 'tb-event-table', @@ -83,6 +84,18 @@ export class EventTableComponent implements OnInit, AfterViewInit, OnDestroy { } } + @Input() + isRuleNodeDebugModeEnabled: boolean; + + @Input() + editingRuleNodeHasScript: boolean; + + @Input() + rulenodeClazz: string; + + @Output() + debugEventSelected = new EventEmitter(null); + @ViewChild(EntitiesTableComponent, {static: true}) entitiesTable: EntitiesTableComponent; eventTableConfig: EventTableConfig; @@ -96,7 +109,8 @@ export class EventTableComponent implements OnInit, AfterViewInit, OnDestroy { private dialog: MatDialog, private overlay: Overlay, private viewContainerRef: ViewContainerRef, - private cd: ChangeDetectorRef) { + private cd: ChangeDetectorRef, + private nodeScriptTestService: NodeScriptTestService) { } ngOnInit() { @@ -114,8 +128,18 @@ export class EventTableComponent implements OnInit, AfterViewInit, OnDestroy { this.debugEventTypes, this.overlay, this.viewContainerRef, - this.cd + this.cd, + this.nodeScriptTestService, + this.isRuleNodeDebugModeEnabled, + this.editingRuleNodeHasScript, + this.rulenodeClazz ); + + this.eventTableConfig.debugEventSelectedSubject.subscribe((debugEventBody: DebugRuleNodeEventBody) => { + if (debugEventBody) { + this.debugEventSelected.emit(debugEventBody); + } + }) } ngAfterViewInit() { diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts index 73f0d5e14a..788a495607 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts @@ -38,6 +38,7 @@ import { TranslateService } from '@ngx-translate/core'; import { JsonObjectEditComponent } from '@shared/components/json-object-edit.component'; import { deepClone } from '@core/utils'; import { RuleChainType } from '@shared/models/rule-chain.models'; +import { DebugRuleNodeEventBody } from '@shared/models/event.models'; @Component({ selector: 'tb-rule-node-config', @@ -92,6 +93,13 @@ export class RuleNodeConfigComponent implements ControlValueAccessor, OnInit, On return this.nodeDefinitionValue; } + @Input() + set debugEventBody(debugEventBody: DebugRuleNodeEventBody) { + if (debugEventBody) { + this.definedConfigComponent?.testScript(debugEventBody); + } + } + definedDirectiveError: string; ruleNodeConfigFormGroup: UntypedFormGroup; diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.html b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.html index b2c73a4bdc..c215b0d21d 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.html +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.html @@ -50,7 +50,8 @@ [ruleNodeId]="ruleNode.ruleNodeId?.id" [ruleChainId]="ruleChainId" [ruleChainType]="ruleChainType" - [nodeDefinition]="ruleNode.component.configurationDescriptor.nodeDefinition"> + [nodeDefinition]="ruleNode.component.configurationDescriptor.nodeDefinition" + [debugEventBody]="debugEventBody">
diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.ts index dad1e715ec..455e70270c 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.ts @@ -27,6 +27,7 @@ import { RuleNodeConfigComponent } from './rule-node-config.component'; import { Router } from '@angular/router'; import { RuleChainType } from '@app/shared/models/rule-chain.models'; import { ComponentClusteringMode } from '@shared/models/component-descriptor.models'; +import { DebugRuleNodeEventBody } from '@shared/models/event.models'; @Component({ selector: 'tb-rule-node', @@ -55,6 +56,9 @@ export class RuleNodeDetailsComponent extends PageComponent implements OnInit, O @Input() isAdd = false; + @Input() + debugEventBody: DebugRuleNodeEventBody; + ruleNodeType = RuleNodeType; entityType = EntityType; diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.html b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.html index 4cdaed942d..15695d9d87 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.html +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.html @@ -100,7 +100,8 @@ (closeDetails)="onEditRuleNodeClosed()" (toggleDetailsEditMode)="onRevertRuleNodeEdit()" (applyDetails)="saveRuleNode()" - [theForm]="tbRuleNode.ruleNodeFormGroup"> + [theForm]="tbRuleNode.ruleNodeFormGroup" + (switchToFirstTab)="onSwitchToFirstTab()">
@@ -111,7 +112,8 @@ [ruleChainId]="ruleChain.id?.id" [ruleChainType]="ruleChainType" [isEdit]="true" - [isReadOnly]="false"> + [isReadOnly]="false" + [debugEventBody]="debugEventBody"> @@ -119,7 +121,12 @@ [defaultEventType]="debugEventTypes.DEBUG_RULE_NODE" [active]="eventsTab.isActive" [tenantId]="ruleChain.tenantId.id" - [entityId]="editingRuleNode.ruleNodeId"> + [entityId]="editingRuleNode.ruleNodeId" + [isRuleNodeDebugModeEnabled]="editingRuleNode?.debugMode" + [editingRuleNodeHasScript]="editingRuleNodeHasScript" + [rulenodeClazz]="editingRuleNode.component.clazz" + (debugEventSelected)="onDebugEventSelected($event)"> +
diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts index d9c6b1b3bb..ff9d9060c8 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts @@ -87,7 +87,7 @@ import { DialogComponent } from '@shared/components/dialog.component'; import { MatMenuTrigger } from '@angular/material/menu'; import { ItemBufferService, RuleNodeConnection } from '@core/services/item-buffer.service'; import { Hotkey } from 'angular2-hotkeys'; -import { DebugEventType, EventType } from '@shared/models/event.models'; +import { DebugEventType, DebugRuleNodeEventBody, EventType } from '@shared/models/event.models'; import { MatMiniFabButton } from '@angular/material/button'; import { TbPopoverService } from '@shared/components/popover.service'; import { VersionControlComponent } from '@home/components/vc/version-control.component'; @@ -153,6 +153,8 @@ export class RuleChainPageComponent extends PageComponent editingRuleNodeAllowCustomLabels = false; editingRuleNodeLinkLabels: {[label: string]: LinkLabel}; editingRuleNodeSourceRuleChainId: string; + debugEventBody: DebugRuleNodeEventBody; + editingRuleNodeHasScript: boolean = false; @ViewChild('tbRuleNode') ruleNodeComponent: RuleNodeDetailsComponent; @ViewChild('tbRuleNodeLink') ruleNodeLinkComponent: RuleNodeLinkComponent; @@ -1110,6 +1112,7 @@ export class RuleChainPageComponent extends PageComponent this.isEditingRuleNode = true; this.editingRuleNodeIndex = this.ruleChainModel.nodes.indexOf(node); this.editingRuleNode = deepClone(node, ['component']); + this.editingRuleNodeHasScript = this.editingRuleNode.configuration.hasOwnProperty('scriptLang'); setTimeout(() => { this.ruleNodeComponent.ruleNodeFormGroup.markAsPristine(); }, 0); @@ -1258,6 +1261,7 @@ export class RuleChainPageComponent extends PageComponent onEditRuleNodeClosed() { this.editingRuleNode = null; this.isEditingRuleNode = false; + this.debugEventBody = null; } onEditRuleNodeLinkClosed() { @@ -1277,6 +1281,16 @@ export class RuleChainPageComponent extends PageComponent this.editingRuleNodeLink = deepClone(edge); } + onDebugEventSelected(debugEventBody: DebugRuleNodeEventBody) { + if (debugEventBody) { + this.debugEventBody = debugEventBody; + } + } + + onSwitchToFirstTab() { + this.selectedRuleNodeTabIndex = 0; + } + saveRuleNode() { this.ruleNodeComponent.validate(); if (this.ruleNodeComponent.ruleNodeFormGroup.valid) { diff --git a/ui-ngx/src/app/shared/models/rule-node.models.ts b/ui-ngx/src/app/shared/models/rule-node.models.ts index d4688546d7..84ea8ddd3e 100644 --- a/ui-ngx/src/app/shared/models/rule-node.models.ts +++ b/ui-ngx/src/app/shared/models/rule-node.models.ts @@ -26,6 +26,7 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { AbstractControl, UntypedFormGroup } from '@angular/forms'; import { RuleChainType } from '@shared/models/rule-chain.models'; +import { DebugRuleNodeEventBody } from '@shared/models/event.models'; export interface RuleNodeConfiguration { [key: string]: any; @@ -75,6 +76,7 @@ export interface IRuleNodeConfigurationComponent { configuration: RuleNodeConfiguration; configurationChanged: Observable; validate(); + testScript? (debugEventBody: DebugRuleNodeEventBody); [key: string]: any; } @@ -427,13 +429,22 @@ export const messageTypeNames = new Map( export const ruleChainNodeClazz = 'org.thingsboard.rule.engine.flow.TbRuleChainInputNode'; export const outputNodeClazz = 'org.thingsboard.rule.engine.flow.TbRuleChainOutputNode'; +export enum RuleNodeClazz { + TbJsFilterNode = 'org.thingsboard.rule.engine.filter.TbJsFilterNode', + TbLogNode = 'org.thingsboard.rule.engine.action.TbLogNode', + TbJsSwitchNode = 'org.thingsboard.rule.engine.filter.TbJsSwitchNode', + TbClearAlarmNode = 'org.thingsboard.rule.engine.action.TbClearAlarmNode', + TbCreateAlarmNode = 'org.thingsboard.rule.engine.action.TbCreateAlarmNode', + TbTransformMsgNode = 'org.thingsboard.rule.engine.transform.TbTransformMsgNode', + TbMsgGeneratorNode = 'org.thingsboard.rule.engine.debug.TbMsgGeneratorNode' +} const ruleNodeClazzHelpLinkMap = { 'org.thingsboard.rule.engine.filter.TbCheckRelationNode': 'ruleNodeCheckRelation', 'org.thingsboard.rule.engine.filter.TbCheckMessageNode': 'ruleNodeCheckExistenceFields', 'org.thingsboard.rule.engine.geo.TbGpsGeofencingFilterNode': 'ruleNodeGpsGeofencingFilter', - 'org.thingsboard.rule.engine.filter.TbJsFilterNode': 'ruleNodeJsFilter', - 'org.thingsboard.rule.engine.filter.TbJsSwitchNode': 'ruleNodeJsSwitch', + [RuleNodeClazz.TbJsFilterNode]: 'ruleNodeJsFilter', + [RuleNodeClazz.TbJsSwitchNode]: 'ruleNodeJsSwitch', 'org.thingsboard.rule.engine.filter.TbAssetTypeSwitchNode': 'ruleNodeAssetProfileSwitch', 'org.thingsboard.rule.engine.filter.TbDeviceTypeSwitchNode': 'ruleNodeDeviceProfileSwitch', 'org.thingsboard.rule.engine.filter.TbCheckAlarmStatusNode': 'ruleNodeCheckAlarmStatus', @@ -452,18 +463,18 @@ const ruleNodeClazzHelpLinkMap = { 'org.thingsboard.rule.engine.metadata.TbGetTenantDetailsNode': 'ruleNodeTenantDetails', 'org.thingsboard.rule.engine.metadata.CalculateDeltaNode': 'ruleNodeCalculateDelta', 'org.thingsboard.rule.engine.transform.TbChangeOriginatorNode': 'ruleNodeChangeOriginator', - 'org.thingsboard.rule.engine.transform.TbTransformMsgNode': 'ruleNodeTransformMsg', + [RuleNodeClazz.TbTransformMsgNode]: 'ruleNodeTransformMsg', 'org.thingsboard.rule.engine.mail.TbMsgToEmailNode': 'ruleNodeMsgToEmail', 'org.thingsboard.rule.engine.action.TbAssignToCustomerNode': 'ruleNodeAssignToCustomer', 'org.thingsboard.rule.engine.action.TbUnassignFromCustomerNode': 'ruleNodeUnassignFromCustomer', - 'org.thingsboard.rule.engine.action.TbClearAlarmNode': 'ruleNodeClearAlarm', - 'org.thingsboard.rule.engine.action.TbCreateAlarmNode': 'ruleNodeCreateAlarm', + [RuleNodeClazz.TbClearAlarmNode]: 'ruleNodeClearAlarm', + [RuleNodeClazz.TbCreateAlarmNode]: 'ruleNodeCreateAlarm', 'org.thingsboard.rule.engine.action.TbCreateRelationNode': 'ruleNodeCreateRelation', 'org.thingsboard.rule.engine.action.TbDeleteRelationNode': 'ruleNodeDeleteRelation', 'org.thingsboard.rule.engine.delay.TbMsgDelayNode': 'ruleNodeMsgDelay', - 'org.thingsboard.rule.engine.debug.TbMsgGeneratorNode': 'ruleNodeMsgGenerator', + [RuleNodeClazz.TbMsgGeneratorNode]: 'ruleNodeMsgGenerator', 'org.thingsboard.rule.engine.geo.TbGpsGeofencingActionNode': 'ruleNodeGpsGeofencingEvents', - 'org.thingsboard.rule.engine.action.TbLogNode': 'ruleNodeLog', + [RuleNodeClazz.TbLogNode]: 'ruleNodeLog', 'org.thingsboard.rule.engine.rpc.TbSendRPCReplyNode': 'ruleNodeRpcCallReply', 'org.thingsboard.rule.engine.rpc.TbSendRPCRequestNode': 'ruleNodeRpcCallRequest', 'org.thingsboard.rule.engine.telemetry.TbMsgAttributesNode': 'ruleNodeSaveAttributes', @@ -499,3 +510,13 @@ export function getRuleNodeHelpLink(component: RuleNodeComponentDescriptor): str } return 'ruleEngine'; } + +export const ruleNodeClazzFunctionNameTranslations = { + [RuleNodeClazz.TbJsFilterNode]: 'rulenode.function-name.filter', + [RuleNodeClazz.TbLogNode]: 'rulenode.function-name.to-string', + [RuleNodeClazz.TbJsSwitchNode]: 'rulenode.function-name.switch', + [RuleNodeClazz.TbClearAlarmNode]: 'rulenode.function-name.details', + [RuleNodeClazz.TbCreateAlarmNode]: 'rulenode.function-name.details', + [RuleNodeClazz.TbTransformMsgNode]: 'rulenode.function-name.transform', + [RuleNodeClazz.TbMsgGeneratorNode]: 'rulenode.function-name.generate' +} diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 341408a615..af513bbaf6 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -3464,7 +3464,16 @@ "output": "Output", "test": "Test", "help": "Help", - "reset-debug-mode": "Reset debug mode in all nodes" + "reset-debug-mode": "Reset debug mode in all nodes", + "test-function": "Test '{{function}}' function with this message", + "function-name": { + "filter": "Filter", + "to-string": "ToString", + "details": "Details", + "generate": "Generate", + "switch": "Switch", + "transform": "Transform" + } }, "timezone": { "timezone": "Timezone", From 552be228a35ad49ca0d8939a25a12324457cd1e7 Mon Sep 17 00:00:00 2001 From: rusikv Date: Mon, 3 Jul 2023 17:13:11 +0300 Subject: [PATCH 10/22] Refactoring --- .../script/node-script-test.service.ts | 6 ++- .../components/details-panel.component.ts | 5 -- .../entity/entities-table.component.ts | 4 ++ .../components/event/event-table-config.ts | 45 +++++++++-------- .../components/event/event-table.component.ts | 36 ++++++++------ .../entity/entity-table-component.models.ts | 1 + .../rulechain/rule-node-config.component.ts | 25 ++++++---- .../rule-node-details.component.html | 2 +- .../rulechain/rule-node-details.component.ts | 7 ++- .../rulechain/rulechain-page.component.html | 9 ++-- .../rulechain/rulechain-page.component.ts | 27 +++++++---- .../src/app/shared/models/rule-node.models.ts | 48 ++++++++----------- .../assets/locale/locale.constant-en_US.json | 10 +--- 13 files changed, 118 insertions(+), 107 deletions(-) diff --git a/ui-ngx/src/app/core/services/script/node-script-test.service.ts b/ui-ngx/src/app/core/services/script/node-script-test.service.ts index c3e0da73ad..fa30934f06 100644 --- a/ui-ngx/src/app/core/services/script/node-script-test.service.ts +++ b/ui-ngx/src/app/core/services/script/node-script-test.service.ts @@ -61,7 +61,8 @@ export class NodeScriptTestService { try { msg = JSON.parse(eventBody.data); } catch (e) {} - } else { + } + if (!msg) { msg = { temperature: 22.4, humidity: 78 @@ -71,7 +72,8 @@ export class NodeScriptTestService { try { metadata = JSON.parse(eventBody.metadata); } catch (e) {} - } else { + } + if (!metadata) { metadata = { deviceName: 'Test Device', deviceType: 'default', diff --git a/ui-ngx/src/app/modules/home/components/details-panel.component.ts b/ui-ngx/src/app/modules/home/components/details-panel.component.ts index ac8d6e3bc3..66facf08d4 100644 --- a/ui-ngx/src/app/modules/home/components/details-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/details-panel.component.ts @@ -56,9 +56,6 @@ export class DetailsPanelComponent extends PageComponent implements OnDestroy { this.theFormValue = value; if (this.theFormValue !== null) { this.formSubscription = this.theFormValue.valueChanges.subscribe(() => { - if (this.isReadOnly) { - this.switchToFirstTab.emit(); - } this.cd.detectChanges() }); } @@ -77,8 +74,6 @@ export class DetailsPanelComponent extends PageComponent implements OnDestroy { applyDetails = new EventEmitter(); @Output() closeSearch = new EventEmitter(); - @Output() - switchToFirstTab = new EventEmitter() isEditValue = false; showSearchPane = false; diff --git a/ui-ngx/src/app/modules/home/components/entity/entities-table.component.ts b/ui-ngx/src/app/modules/home/components/entity/entities-table.component.ts index b868fd1e47..46a7c966c8 100644 --- a/ui-ngx/src/app/modules/home/components/entity/entities-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/entity/entities-table.component.ts @@ -637,6 +637,10 @@ export class EntitiesTableComponent extends PageComponent implements IEntitiesTa } } + cellActionDescriptorsUpdated() { + this.cellActionDescriptors = [...this.entitiesTableConfig.cellActionDescriptors]; + } + headerCellStyle(column: EntityColumn>) { const index = this.entitiesTableConfig.columns.indexOf(column); let res = this.headerCellStyleCache[index]; diff --git a/ui-ngx/src/app/modules/home/components/event/event-table-config.ts b/ui-ngx/src/app/modules/home/components/event/event-table-config.ts index 51bd99fde0..7382633e33 100644 --- a/ui-ngx/src/app/modules/home/components/event/event-table-config.ts +++ b/ui-ngx/src/app/modules/home/components/event/event-table-config.ts @@ -30,7 +30,7 @@ import { EntityId } from '@shared/models/id/entity-id'; import { EventService } from '@app/core/http/event.service'; import { EventTableHeaderComponent } from '@home/components/event/event-table-header.component'; import { EntityTypeResource } from '@shared/models/entity-type.models'; -import { BehaviorSubject, Observable } from 'rxjs'; +import { Observable } from 'rxjs'; import { PageData } from '@shared/models/page/page-data'; import { Direction } from '@shared/models/page/sort-order'; import { DialogService } from '@core/services/dialog.service'; @@ -41,7 +41,7 @@ import { } from '@home/components/event/event-content-dialog.component'; import { isEqual, sortObjectKeys } from '@core/utils'; import { ConnectedPosition, Overlay, OverlayConfig, OverlayRef } from '@angular/cdk/overlay'; -import { ChangeDetectorRef, Injector, StaticProvider, ViewContainerRef } from '@angular/core'; +import { ChangeDetectorRef, EventEmitter, Injector, StaticProvider, ViewContainerRef } from '@angular/core'; import { ComponentPortal } from '@angular/cdk/portal'; import { EVENT_FILTER_PANEL_DATA, @@ -50,7 +50,6 @@ import { FilterEntityColumn } from '@home/components/event/event-filter-panel.component'; import { NodeScriptTestService } from '@core/services/script/node-script-test.service'; -import { ruleNodeClazzFunctionNameTranslations } from '@shared/models/rule-node.models'; export class EventTableConfig extends EntityTableConfig { @@ -63,6 +62,7 @@ export class EventTableConfig extends EntityTableConfig { set eventType(eventType: EventType | DebugEventType) { if (this.eventTypeValue !== eventType) { this.eventTypeValue = eventType; + this.updateCellAction(); this.updateColumns(true); this.updateFilterColumns(); } @@ -74,8 +74,6 @@ export class EventTableConfig extends EntityTableConfig { eventTypes: Array; - debugEventSelectedSubject = new BehaviorSubject(null); - constructor(private eventService: EventService, private dialogService: DialogService, private translate: TranslateService, @@ -90,9 +88,8 @@ export class EventTableConfig extends EntityTableConfig { private viewContainerRef: ViewContainerRef, private cd: ChangeDetectorRef, private nodeScriptTestService: NodeScriptTestService, - private isRuleNodeDebugModeEnabled: boolean, - private editingRuleNodeHasScript: boolean, - private rulenodeClazz: string) { + public testButtonLabel?: string, + private debugEventSelected?: EventEmitter) { super(); this.loadDataOnInit = false; this.tableTitle = ''; @@ -128,6 +125,7 @@ export class EventTableConfig extends EntityTableConfig { this.defaultSortOrder = {property: 'createdTime', direction: Direction.DESC}; this.updateColumns(); + this.updateCellAction(); this.updateFilterColumns(); this.headerActionDescriptors.push({ @@ -325,18 +323,6 @@ export class EventTableConfig extends EntityTableConfig { onAction: ($event, entity) => this.showContent($event, entity.body.error, 'event.error') }, - '48px'), - new EntityActionTableColumn('test', '', - { - name: this.translate.instant('rulenode.test-function', - {function: this.translate.instant(ruleNodeClazzFunctionNameTranslations[this.rulenodeClazz])}), - icon: 'bug_report', - isEnabled: (entity) => this.isRuleNodeDebugModeEnabled && entity.body.type === 'IN' && - this.editingRuleNodeHasScript, - onAction: ($event, entity) => { - this.debugEventSelectedSubject.next(entity.body); - } - }, '48px') ); break; @@ -369,6 +355,25 @@ export class EventTableConfig extends EntityTableConfig { } } + updateCellAction() { + this.cellActionDescriptors = []; + switch (this.eventType) { + case DebugEventType.DEBUG_RULE_NODE: + if (this.testButtonLabel) { + this.cellActionDescriptors.push({ + name: this.translate.instant('rulenode.test-with-this-message', {test: this.testButtonLabel}), + icon: 'bug_report', + isEnabled: (entity) => entity.body.type === 'IN', + onAction: ($event, entity) => { + this.debugEventSelected.next(entity.body); + } + }); + } + break; + } + this.getTable()?.cellActionDescriptorsUpdated(); + } + showContent($event: MouseEvent, content: string, title: string, contentType: ContentType = null, sortKeys = false): void { if ($event) { $event.stopPropagation(); diff --git a/ui-ngx/src/app/modules/home/components/event/event-table.component.ts b/ui-ngx/src/app/modules/home/components/event/event-table.component.ts index 4781b4811d..80394de979 100644 --- a/ui-ngx/src/app/modules/home/components/event/event-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/event/event-table.component.ts @@ -36,6 +36,7 @@ import { DebugEventType, DebugRuleNodeEventBody, EventType } from '@shared/model import { Overlay } from '@angular/cdk/overlay'; import { Subscription } from 'rxjs'; import { NodeScriptTestService } from '@core/services/script/node-script-test.service'; +import { isNotEmptyStr } from '@core/utils'; @Component({ selector: 'tb-event-table', @@ -60,6 +61,10 @@ export class EventTableComponent implements OnInit, AfterViewInit, OnDestroy { dirtyValue = false; entityIdValue: EntityId; + get active(): boolean { + return this.activeValue; + } + @Input() set active(active: boolean) { if (this.activeValue !== active) { @@ -84,14 +89,24 @@ export class EventTableComponent implements OnInit, AfterViewInit, OnDestroy { } } - @Input() - isRuleNodeDebugModeEnabled: boolean; + private ruleNodeTestButtonLabelValue: string; - @Input() - editingRuleNodeHasScript: boolean; + get ruleNodeTestButtonLabel(): string { + return this.ruleNodeTestButtonLabelValue; + } @Input() - rulenodeClazz: string; + set ruleNodeTestButtonLabel(value: string) { + if (isNotEmptyStr(value)) { + this.ruleNodeTestButtonLabelValue = value; + } else { + this.ruleNodeTestButtonLabelValue = ''; + } + if (this.eventTableConfig) { + this.eventTableConfig.testButtonLabel = this.ruleNodeTestButtonLabel; + this.eventTableConfig.updateCellAction(); + } + } @Output() debugEventSelected = new EventEmitter(null); @@ -130,16 +145,9 @@ export class EventTableComponent implements OnInit, AfterViewInit, OnDestroy { this.viewContainerRef, this.cd, this.nodeScriptTestService, - this.isRuleNodeDebugModeEnabled, - this.editingRuleNodeHasScript, - this.rulenodeClazz + this.ruleNodeTestButtonLabel, + this.debugEventSelected ); - - this.eventTableConfig.debugEventSelectedSubject.subscribe((debugEventBody: DebugRuleNodeEventBody) => { - if (debugEventBody) { - this.debugEventSelected.emit(debugEventBody); - } - }) } ngAfterViewInit() { diff --git a/ui-ngx/src/app/modules/home/models/entity/entity-table-component.models.ts b/ui-ngx/src/app/modules/home/models/entity/entity-table-component.models.ts index 033747f6d3..a6e5ada7bf 100644 --- a/ui-ngx/src/app/modules/home/models/entity/entity-table-component.models.ts +++ b/ui-ngx/src/app/modules/home/models/entity/entity-table-component.models.ts @@ -80,6 +80,7 @@ export interface IEntitiesTableComponent { exitFilterMode(): void; resetSortAndFilter(update?: boolean, preserveTimewindow?: boolean): void; columnsUpdated(resetData?: boolean): void; + cellActionDescriptorsUpdated(): void; headerCellStyle(column: EntityColumn>): any; clearCellCache(col: number, row: number): void; cellContent(entity: BaseData, column: EntityColumn>, row: number): any; diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts index 788a495607..6c19507301 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts @@ -18,14 +18,22 @@ import { AfterViewInit, Component, ComponentRef, + EventEmitter, forwardRef, Input, OnDestroy, OnInit, + Output, ViewChild, ViewContainerRef } from '@angular/core'; -import { ControlValueAccessor, UntypedFormBuilder, UntypedFormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; +import { + ControlValueAccessor, + NG_VALUE_ACCESSOR, + UntypedFormBuilder, + UntypedFormGroup, + Validators +} from '@angular/forms'; import { IRuleNodeConfigurationComponent, RuleNodeConfiguration, @@ -38,7 +46,6 @@ import { TranslateService } from '@ngx-translate/core'; import { JsonObjectEditComponent } from '@shared/components/json-object-edit.component'; import { deepClone } from '@core/utils'; import { RuleChainType } from '@shared/models/rule-chain.models'; -import { DebugRuleNodeEventBody } from '@shared/models/event.models'; @Component({ selector: 'tb-rule-node-config', @@ -77,6 +84,9 @@ export class RuleNodeConfigComponent implements ControlValueAccessor, OnInit, On @Input() ruleChainType: RuleChainType; + @Output() + initRuleNode = new EventEmitter(); + nodeDefinitionValue: RuleNodeDefinition; @Input() @@ -86,6 +96,7 @@ export class RuleNodeConfigComponent implements ControlValueAccessor, OnInit, On if (this.nodeDefinitionValue) { this.validateDefinedDirective(); } + setTimeout(() => this.initRuleNode.emit()); } } @@ -93,21 +104,15 @@ export class RuleNodeConfigComponent implements ControlValueAccessor, OnInit, On return this.nodeDefinitionValue; } - @Input() - set debugEventBody(debugEventBody: DebugRuleNodeEventBody) { - if (debugEventBody) { - this.definedConfigComponent?.testScript(debugEventBody); - } - } - definedDirectiveError: string; ruleNodeConfigFormGroup: UntypedFormGroup; changeSubscription: Subscription; + definedConfigComponent: IRuleNodeConfigurationComponent; + private definedConfigComponentRef: ComponentRef; - private definedConfigComponent: IRuleNodeConfigurationComponent; private configuration: RuleNodeConfiguration; diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.html b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.html index c215b0d21d..2f925ded60 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.html +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.html @@ -51,7 +51,7 @@ [ruleChainId]="ruleChainId" [ruleChainType]="ruleChainType" [nodeDefinition]="ruleNode.component.configurationDescriptor.nodeDefinition" - [debugEventBody]="debugEventBody"> + (initRuleNode)="initRuleNode.emit($event)">
diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.ts index 455e70270c..7b0f426c35 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.ts @@ -14,7 +14,7 @@ /// limitations under the License. /// -import { Component, Input, OnChanges, OnInit, SimpleChanges, ViewChild } from '@angular/core'; +import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core'; import { PageComponent } from '@shared/components/page.component'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @@ -27,7 +27,6 @@ import { RuleNodeConfigComponent } from './rule-node-config.component'; import { Router } from '@angular/router'; import { RuleChainType } from '@app/shared/models/rule-chain.models'; import { ComponentClusteringMode } from '@shared/models/component-descriptor.models'; -import { DebugRuleNodeEventBody } from '@shared/models/event.models'; @Component({ selector: 'tb-rule-node', @@ -56,8 +55,8 @@ export class RuleNodeDetailsComponent extends PageComponent implements OnInit, O @Input() isAdd = false; - @Input() - debugEventBody: DebugRuleNodeEventBody; + @Output() + initRuleNode = new EventEmitter(); ruleNodeType = RuleNodeType; entityType = EntityType; diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.html b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.html index 15695d9d87..5e20a6a8e2 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.html +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.html @@ -100,8 +100,7 @@ (closeDetails)="onEditRuleNodeClosed()" (toggleDetailsEditMode)="onRevertRuleNodeEdit()" (applyDetails)="saveRuleNode()" - [theForm]="tbRuleNode.ruleNodeFormGroup" - (switchToFirstTab)="onSwitchToFirstTab()"> + [theForm]="tbRuleNode.ruleNodeFormGroup">
@@ -113,7 +112,7 @@ [ruleChainType]="ruleChainType" [isEdit]="true" [isReadOnly]="false" - [debugEventBody]="debugEventBody"> + (initRuleNode)="onRuleNodeInit()"> @@ -122,9 +121,7 @@ [active]="eventsTab.isActive" [tenantId]="ruleChain.tenantId.id" [entityId]="editingRuleNode.ruleNodeId" - [isRuleNodeDebugModeEnabled]="editingRuleNode?.debugMode" - [editingRuleNodeHasScript]="editingRuleNodeHasScript" - [rulenodeClazz]="editingRuleNode.component.clazz" + [ruleNodeTestButtonLabel]="ruleNodeTestButtonLabel" (debugEventSelected)="onDebugEventSelected($event)"> diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts index ff9d9060c8..d5ea093721 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts @@ -153,8 +153,7 @@ export class RuleChainPageComponent extends PageComponent editingRuleNodeAllowCustomLabels = false; editingRuleNodeLinkLabels: {[label: string]: LinkLabel}; editingRuleNodeSourceRuleChainId: string; - debugEventBody: DebugRuleNodeEventBody; - editingRuleNodeHasScript: boolean = false; + ruleNodeTestButtonLabel: string; @ViewChild('tbRuleNode') ruleNodeComponent: RuleNodeDetailsComponent; @ViewChild('tbRuleNodeLink') ruleNodeLinkComponent: RuleNodeLinkComponent; @@ -1112,7 +1111,6 @@ export class RuleChainPageComponent extends PageComponent this.isEditingRuleNode = true; this.editingRuleNodeIndex = this.ruleChainModel.nodes.indexOf(node); this.editingRuleNode = deepClone(node, ['component']); - this.editingRuleNodeHasScript = this.editingRuleNode.configuration.hasOwnProperty('scriptLang'); setTimeout(() => { this.ruleNodeComponent.ruleNodeFormGroup.markAsPristine(); }, 0); @@ -1261,7 +1259,6 @@ export class RuleChainPageComponent extends PageComponent onEditRuleNodeClosed() { this.editingRuleNode = null; this.isEditingRuleNode = false; - this.debugEventBody = null; } onEditRuleNodeLinkClosed() { @@ -1282,13 +1279,25 @@ export class RuleChainPageComponent extends PageComponent } onDebugEventSelected(debugEventBody: DebugRuleNodeEventBody) { - if (debugEventBody) { - this.debugEventBody = debugEventBody; - } + if (this.ruleNodeComponent.ruleNodeConfigComponent.useDefinedDirective() && + this.ruleNodeComponent.ruleNodeConfigComponent.definedConfigComponent.getSupportTestFunction() && + this.ruleNodeComponent.ruleNodeConfigComponent.definedConfigComponent.testScript$) { + this.ruleNodeComponent.ruleNodeConfigComponent.definedConfigComponent.testScript$(debugEventBody) + .subscribe((value) => { + if (value) { + this.selectedRuleNodeTabIndex = 0; + } + }) + } } - onSwitchToFirstTab() { - this.selectedRuleNodeTabIndex = 0; + onRuleNodeInit() { + if (this.ruleNodeComponent.ruleNodeConfigComponent.useDefinedDirective() && + this.ruleNodeComponent.ruleNodeConfigComponent.definedConfigComponent.getSupportTestFunction()) { + this.ruleNodeTestButtonLabel = this.ruleNodeComponent.ruleNodeConfigComponent.definedConfigComponent.getTestButtonLabel(); + } else { + this.ruleNodeTestButtonLabel = ''; + } } saveRuleNode() { diff --git a/ui-ngx/src/app/shared/models/rule-node.models.ts b/ui-ngx/src/app/shared/models/rule-node.models.ts index 84ea8ddd3e..dd427aaf09 100644 --- a/ui-ngx/src/app/shared/models/rule-node.models.ts +++ b/ui-ngx/src/app/shared/models/rule-node.models.ts @@ -27,6 +27,7 @@ import { AppState } from '@core/core.state'; import { AbstractControl, UntypedFormGroup } from '@angular/forms'; import { RuleChainType } from '@shared/models/rule-chain.models'; import { DebugRuleNodeEventBody } from '@shared/models/event.models'; +import { TranslateService } from '@ngx-translate/core'; export interface RuleNodeConfiguration { [key: string]: any; @@ -76,7 +77,9 @@ export interface IRuleNodeConfigurationComponent { configuration: RuleNodeConfiguration; configurationChanged: Observable; validate(); - testScript? (debugEventBody: DebugRuleNodeEventBody); + getSupportTestFunction(): boolean; + getTestButtonLabel? (): string; + testScript$? (debugEventBody?: DebugRuleNodeEventBody): Observable; [key: string]: any; } @@ -112,7 +115,8 @@ export abstract class RuleNodeConfigurationComponent extends PageComponent imple configurationChangedEmiter = new EventEmitter(); configurationChanged = this.configurationChangedEmiter.asObservable(); - protected constructor(@Inject(Store) protected store: Store) { + protected constructor(@Inject(Store) protected store: Store, + @Inject(TranslateService) protected translate: TranslateService) { super(store); } @@ -130,6 +134,14 @@ export abstract class RuleNodeConfigurationComponent extends PageComponent imple this.onValidate(); } + getSupportTestFunction(): boolean { + return false; + } + + getTestButtonLabel(): string { + return this.translate.instant('rulenode.test-script-function'); + } + protected setupConfiguration(configuration: RuleNodeConfiguration) { this.onConfigurationSet(this.prepareInputConfig(configuration)); this.updateValidators(false); @@ -429,22 +441,13 @@ export const messageTypeNames = new Map( export const ruleChainNodeClazz = 'org.thingsboard.rule.engine.flow.TbRuleChainInputNode'; export const outputNodeClazz = 'org.thingsboard.rule.engine.flow.TbRuleChainOutputNode'; -export enum RuleNodeClazz { - TbJsFilterNode = 'org.thingsboard.rule.engine.filter.TbJsFilterNode', - TbLogNode = 'org.thingsboard.rule.engine.action.TbLogNode', - TbJsSwitchNode = 'org.thingsboard.rule.engine.filter.TbJsSwitchNode', - TbClearAlarmNode = 'org.thingsboard.rule.engine.action.TbClearAlarmNode', - TbCreateAlarmNode = 'org.thingsboard.rule.engine.action.TbCreateAlarmNode', - TbTransformMsgNode = 'org.thingsboard.rule.engine.transform.TbTransformMsgNode', - TbMsgGeneratorNode = 'org.thingsboard.rule.engine.debug.TbMsgGeneratorNode' -} const ruleNodeClazzHelpLinkMap = { 'org.thingsboard.rule.engine.filter.TbCheckRelationNode': 'ruleNodeCheckRelation', 'org.thingsboard.rule.engine.filter.TbCheckMessageNode': 'ruleNodeCheckExistenceFields', 'org.thingsboard.rule.engine.geo.TbGpsGeofencingFilterNode': 'ruleNodeGpsGeofencingFilter', - [RuleNodeClazz.TbJsFilterNode]: 'ruleNodeJsFilter', - [RuleNodeClazz.TbJsSwitchNode]: 'ruleNodeJsSwitch', + 'org.thingsboard.rule.engine.filter.TbJsFilterNode': 'ruleNodeJsFilter', + 'org.thingsboard.rule.engine.filter.TbJsSwitchNode': 'ruleNodeJsSwitch', 'org.thingsboard.rule.engine.filter.TbAssetTypeSwitchNode': 'ruleNodeAssetProfileSwitch', 'org.thingsboard.rule.engine.filter.TbDeviceTypeSwitchNode': 'ruleNodeDeviceProfileSwitch', 'org.thingsboard.rule.engine.filter.TbCheckAlarmStatusNode': 'ruleNodeCheckAlarmStatus', @@ -463,18 +466,18 @@ const ruleNodeClazzHelpLinkMap = { 'org.thingsboard.rule.engine.metadata.TbGetTenantDetailsNode': 'ruleNodeTenantDetails', 'org.thingsboard.rule.engine.metadata.CalculateDeltaNode': 'ruleNodeCalculateDelta', 'org.thingsboard.rule.engine.transform.TbChangeOriginatorNode': 'ruleNodeChangeOriginator', - [RuleNodeClazz.TbTransformMsgNode]: 'ruleNodeTransformMsg', + 'org.thingsboard.rule.engine.transform.TbTransformMsgNode': 'ruleNodeTransformMsg', 'org.thingsboard.rule.engine.mail.TbMsgToEmailNode': 'ruleNodeMsgToEmail', 'org.thingsboard.rule.engine.action.TbAssignToCustomerNode': 'ruleNodeAssignToCustomer', 'org.thingsboard.rule.engine.action.TbUnassignFromCustomerNode': 'ruleNodeUnassignFromCustomer', - [RuleNodeClazz.TbClearAlarmNode]: 'ruleNodeClearAlarm', - [RuleNodeClazz.TbCreateAlarmNode]: 'ruleNodeCreateAlarm', + 'org.thingsboard.rule.engine.action.TbClearAlarmNode': 'ruleNodeClearAlarm', + 'org.thingsboard.rule.engine.action.TbCreateAlarmNode': 'ruleNodeCreateAlarm', 'org.thingsboard.rule.engine.action.TbCreateRelationNode': 'ruleNodeCreateRelation', 'org.thingsboard.rule.engine.action.TbDeleteRelationNode': 'ruleNodeDeleteRelation', 'org.thingsboard.rule.engine.delay.TbMsgDelayNode': 'ruleNodeMsgDelay', - [RuleNodeClazz.TbMsgGeneratorNode]: 'ruleNodeMsgGenerator', + 'org.thingsboard.rule.engine.debug.TbMsgGeneratorNode': 'ruleNodeMsgGenerator', 'org.thingsboard.rule.engine.geo.TbGpsGeofencingActionNode': 'ruleNodeGpsGeofencingEvents', - [RuleNodeClazz.TbLogNode]: 'ruleNodeLog', + 'org.thingsboard.rule.engine.action.TbLogNode': 'ruleNodeLog', 'org.thingsboard.rule.engine.rpc.TbSendRPCReplyNode': 'ruleNodeRpcCallReply', 'org.thingsboard.rule.engine.rpc.TbSendRPCRequestNode': 'ruleNodeRpcCallRequest', 'org.thingsboard.rule.engine.telemetry.TbMsgAttributesNode': 'ruleNodeSaveAttributes', @@ -511,12 +514,3 @@ export function getRuleNodeHelpLink(component: RuleNodeComponentDescriptor): str return 'ruleEngine'; } -export const ruleNodeClazzFunctionNameTranslations = { - [RuleNodeClazz.TbJsFilterNode]: 'rulenode.function-name.filter', - [RuleNodeClazz.TbLogNode]: 'rulenode.function-name.to-string', - [RuleNodeClazz.TbJsSwitchNode]: 'rulenode.function-name.switch', - [RuleNodeClazz.TbClearAlarmNode]: 'rulenode.function-name.details', - [RuleNodeClazz.TbCreateAlarmNode]: 'rulenode.function-name.details', - [RuleNodeClazz.TbTransformMsgNode]: 'rulenode.function-name.transform', - [RuleNodeClazz.TbMsgGeneratorNode]: 'rulenode.function-name.generate' -} diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index d3b374f1ec..ef94480aa8 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -3467,15 +3467,7 @@ "test": "Test", "help": "Help", "reset-debug-mode": "Reset debug mode in all nodes", - "test-function": "Test '{{function}}' function with this message", - "function-name": { - "filter": "Filter", - "to-string": "ToString", - "details": "Details", - "generate": "Generate", - "switch": "Switch", - "transform": "Transform" - } + "test-with-this-message": "{{test}} with this message" }, "timezone": { "timezone": "Timezone", From e5c99cf92f7f79f263573841bd6026bed2955371 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Tue, 11 Jul 2023 14:55:52 +0300 Subject: [PATCH 11/22] UI: Added on unit input to show the clear button when hovering the element --- .../shared/components/unit-input.component.html | 2 +- ui-ngx/src/form.scss | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/ui-ngx/src/app/shared/components/unit-input.component.html b/ui-ngx/src/app/shared/components/unit-input.component.html index dee26af8d0..141ab322d4 100644 --- a/ui-ngx/src/app/shared/components/unit-input.component.html +++ b/ui-ngx/src/app/shared/components/unit-input.component.html @@ -15,7 +15,7 @@ limitations under the License. --> - + Date: Tue, 11 Jul 2023 15:10:06 +0300 Subject: [PATCH 12/22] UI: Metrial icons selector --- .../ThingsboardSecurityConfiguration.java | 30 +- .../app/core/services/resources.service.ts | 22 + .../dialog/material-icons-dialog.component.ts | 15 +- .../components/material-icons.component.ts | 24 + ui-ngx/src/app/shared/models/icon.models.ts | 36 + .../assets/fonts/MaterialIcons-Regular.ttf | Bin 337868 -> 356840 bytes .../src/assets/metadata/material-icons.json | 6367 +++++++++++++++++ 7 files changed, 6484 insertions(+), 10 deletions(-) create mode 100644 ui-ngx/src/app/shared/components/material-icons.component.ts create mode 100644 ui-ngx/src/app/shared/models/icon.models.ts create mode 100644 ui-ngx/src/assets/metadata/material-icons.json diff --git a/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java b/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java index 793670f0ab..0cf820c6f3 100644 --- a/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java +++ b/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java @@ -19,9 +19,11 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.security.SecurityProperties; +import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; +import org.springframework.http.HttpHeaders; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.DefaultAuthenticationEventPublisher; import org.springframework.security.config.annotation.ObjectPostProcessor; @@ -29,7 +31,6 @@ import org.springframework.security.config.annotation.authentication.builders.Au import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestResolver; @@ -37,9 +38,11 @@ import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.header.writers.StaticHeadersWriter; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; +import org.springframework.web.filter.ShallowEtagHeaderFilter; import org.thingsboard.server.dao.oauth2.OAuth2Configuration; import org.thingsboard.server.exception.ThingsboardErrorResponseHandler; import org.thingsboard.server.queue.util.TbCoreComponent; @@ -119,6 +122,17 @@ public class ThingsboardSecurityConfiguration { @Autowired private RateLimitProcessingFilter rateLimitProcessingFilter; + @Bean + protected FilterRegistrationBean buildEtagFilter() throws Exception { + ShallowEtagHeaderFilter etagFilter = new ShallowEtagHeaderFilter(); + etagFilter.setWriteWeakETag(true); + FilterRegistrationBean filterRegistrationBean + = new FilterRegistrationBean<>( etagFilter); + filterRegistrationBean.addUrlPatterns("*.js","*.css","*.ico","/assets/*","/static/*"); + filterRegistrationBean.setName("etagFilter"); + return filterRegistrationBean; + } + @Bean protected RestLoginProcessingFilter buildRestLoginProcessingFilter() throws Exception { RestLoginProcessingFilter filter = new RestLoginProcessingFilter(FORM_BASED_LOGIN_ENTRY_POINT, successHandler, failureHandler); @@ -181,8 +195,18 @@ public class ThingsboardSecurityConfiguration { private OAuth2AuthorizationRequestResolver oAuth2AuthorizationRequestResolver; @Bean - public WebSecurityCustomizer webSecurityCustomizer() { - return (web) -> web.ignoring().antMatchers("/*.js","/*.css","/*.ico","/assets/**","/static/**"); + @Order(0) + SecurityFilterChain resources(HttpSecurity http) throws Exception { + http + .requestMatchers((matchers) -> matchers.antMatchers("/*.js","/*.css","/*.ico","/assets/**","/static/**")) + .headers().defaultsDisabled() + .addHeaderWriter(new StaticHeadersWriter(HttpHeaders.CACHE_CONTROL, "max-age=0, public")) + .and() + .authorizeHttpRequests((authorize) -> authorize.anyRequest().permitAll()) + .requestCache().disable() + .securityContext().disable() + .sessionManagement().disable(); + return http.build(); } @Bean diff --git a/ui-ngx/src/app/core/services/resources.service.ts b/ui-ngx/src/app/core/services/resources.service.ts index 70084153e8..f407e8f354 100644 --- a/ui-ngx/src/app/core/services/resources.service.ts +++ b/ui-ngx/src/app/core/services/resources.service.ts @@ -47,6 +47,7 @@ export interface ModulesWithFactories { }) export class ResourcesService { + private loadedJsonResources: { [url: string]: ReplaySubject } = {}; private loadedResources: { [url: string]: ReplaySubject } = {}; private loadedModules: { [url: string]: ReplaySubject[]> } = {}; private loadedModulesAndFactories: { [url: string]: ReplaySubject } = {}; @@ -61,6 +62,27 @@ export class ResourcesService { this.store.pipe(select(selectIsAuthenticated)).subscribe(() => this.clearModulesCache()); } + public loadJsonResource(url: string): Observable { + if (this.loadedJsonResources[url]) { + return this.loadedJsonResources[url].asObservable(); + } + const subject = new ReplaySubject(); + this.loadedJsonResources[url] = subject; + this.http.get(url).subscribe( + { + next: (o) => { + this.loadedJsonResources[url].next(o); + this.loadedJsonResources[url].complete(); + }, + error: () => { + this.loadedJsonResources[url].error(new Error(`Unable to load ${url}`)); + delete this.loadedJsonResources[url]; + } + } + ); + return subject.asObservable(); + } + public loadResource(url: string): Observable { if (this.loadedResources[url]) { return this.loadedResources[url].asObservable(); diff --git a/ui-ngx/src/app/shared/components/dialog/material-icons-dialog.component.ts b/ui-ngx/src/app/shared/components/dialog/material-icons-dialog.component.ts index cfa4c3d44f..e63b6a0c9c 100644 --- a/ui-ngx/src/app/shared/components/dialog/material-icons-dialog.component.ts +++ b/ui-ngx/src/app/shared/components/dialog/material-icons-dialog.component.ts @@ -22,8 +22,10 @@ import { Router } from '@angular/router'; import { DialogComponent } from '@shared/components/dialog.component'; import { UtilsService } from '@core/services/utils.service'; import { UntypedFormControl } from '@angular/forms'; -import { merge, Observable, of } from 'rxjs'; +import { merge, Observable } from 'rxjs'; import { delay, map, mapTo, mergeMap, share, startWith, tap } from 'rxjs/operators'; +import { ResourcesService } from '@core/services/resources.service'; +import { getMaterialIcons } from '@shared/models/icon.models'; export interface MaterialIconsDialogData { icon: string; @@ -50,6 +52,7 @@ export class MaterialIconsDialogComponent extends DialogComponent) { super(store, router, dialogRef); this.selectedIcon = data.icon; @@ -58,15 +61,13 @@ export class MaterialIconsDialogComponent extends DialogComponent { - return {firstTime: false, showAll}; - }), - startWith<{firstTime: boolean, showAll: boolean}>({firstTime: true, showAll: false}), + map((showAll) => ({firstTime: false, showAll})), + startWith<{firstTime: boolean; showAll: boolean}>({firstTime: true, showAll: false}), mergeMap((data) => { + const res = getMaterialIcons(this.resourcesService, data.showAll, ''); if (data.showAll) { - return this.utils.getMaterialIcons().pipe(delay(100)); + return res.pipe(delay(100)); } else { - const res = of(this.utils.getCommonMaterialIcons()); return data.firstTime ? res : res.pipe(delay(50)); } }), diff --git a/ui-ngx/src/app/shared/components/material-icons.component.ts b/ui-ngx/src/app/shared/components/material-icons.component.ts new file mode 100644 index 0000000000..5588540018 --- /dev/null +++ b/ui-ngx/src/app/shared/components/material-icons.component.ts @@ -0,0 +1,24 @@ +import { PageComponent } from '@shared/components/page.component'; +import { OnInit } from '@angular/core'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { UntypedFormControl } from '@angular/forms'; +import { BehaviorSubject, Observable, ReplaySubject } from 'rxjs'; + +export class MaterialIconsComponent extends PageComponent implements OnInit { + + searchIconsControl: UntypedFormControl; + showAllSubject = new BehaviorSubject(false); + + icons$: Observable>; + + constructor(protected store: Store) { + super(store); + this.searchIconsControl = new UntypedFormControl(''); + } + + ngOnInit(): void { + + } + +} diff --git a/ui-ngx/src/app/shared/models/icon.models.ts b/ui-ngx/src/app/shared/models/icon.models.ts new file mode 100644 index 0000000000..c774b65ae5 --- /dev/null +++ b/ui-ngx/src/app/shared/models/icon.models.ts @@ -0,0 +1,36 @@ +import { Unit, units } from '@shared/models/unit.models'; +import { ResourcesService } from '@core/services/resources.service'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { isEmptyStr, isNotEmptyStr } from '@core/utils'; + +export interface MaterialIcon { + name: string; + tags: string[]; +} + +export const iconByName = (icons: Array, name: string): MaterialIcon => icons.find(i => i.name === name); + +const searchIconTags = (icon: MaterialIcon, searchText: string): boolean => + !!icon.tags.find(t => t.toUpperCase().includes(searchText.toUpperCase())); + +const searchIcons = (_icons: Array, searchText: string): Array => _icons.filter( + i => i.name.toUpperCase().includes(searchText.toUpperCase()) || + searchIconTags(i, searchText) +); + +const getCommonMaterialIcons = (icons: Array): Array => icons.slice(0, 44); + +export const getMaterialIcons = (resourcesService: ResourcesService, all = false, searchText: string): Observable => + resourcesService.loadJsonResource>('/assets/metadata/material-icons.json').pipe( + map((icons) => { + if (isNotEmptyStr(searchText)) { + return searchIcons(icons, searchText); + } else if (!all) { + return getCommonMaterialIcons(icons); + } else { + return icons; + } + }), + map((icons) => icons.map(icon => icon.name)) + ); diff --git a/ui-ngx/src/assets/fonts/MaterialIcons-Regular.ttf b/ui-ngx/src/assets/fonts/MaterialIcons-Regular.ttf index be4be29c8664ae8199bd0fa6c8df9e8e140d354f..9d09b0feb85c35beeaddd31246be0b7c8e0e69a4 100644 GIT binary patch delta 30269 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 Hj(EQS<1qb( delta 12282 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 diff --git a/ui-ngx/src/assets/metadata/material-icons.json b/ui-ngx/src/assets/metadata/material-icons.json new file mode 100644 index 0000000000..7f12a1e605 --- /dev/null +++ b/ui-ngx/src/assets/metadata/material-icons.json @@ -0,0 +1,6367 @@ +[ { + "name" : "more_horiz", + "tags" : [ "3", "DISABLE_IOS", "app", "application", "components", "disable_ios", "dots", "etc", "horiz", "horizontal", "interface", "ios", "more", "screen", "site", "three", "ui", "ux", "web", "website" ] +}, { + "name" : "more_vert", + "tags" : [ "3", "DISABLE_IOS", "android", "app", "application", "components", "disable_ios", "dots", "etc", "interface", "more", "screen", "site", "three", "ui", "ux", "vert", "vertical", "web", "website" ] +}, { + "name" : "open_in_new", + "tags" : [ "app", "application", "arrow", "box", "components", "in", "interface", "new", "open", "right", "screen", "site", "ui", "up", "ux", "web", "website", "window" ] +}, { + "name" : "visibility", + "tags" : [ "eye", "on", "reveal", "see", "show", "view", "visibility" ] +}, { + "name" : "play_arrow", + "tags" : [ "arrow", "control", "controls", "media", "music", "play", "video" ] +}, { + "name" : "arrow_back", + "tags" : [ "DISABLE_IOS", "app", "application", "arrow", "back", "components", "direction", "disable_ios", "interface", "left", "navigation", "previous", "screen", "site", "ui", "ux", "web", "website" ] +}, { + "name" : "arrow_downward", + "tags" : [ "app", "application", "arrow", "components", "direction", "down", "downward", "interface", "navigation", "screen", "site", "ui", "ux", "web", "website" ] +}, { + "name" : "arrow_forward", + "tags" : [ "app", "application", "arrow", "arrows", "components", "direction", "forward", "interface", "navigation", "right", "screen", "site", "ui", "ux", "web", "website" ] +}, { + "name" : "arrow_upward", + "tags" : [ "app", "application", "arrow", "components", "direction", "interface", "navigation", "screen", "site", "ui", "up", "upward", "ux", "web", "website" ] +}, { + "name" : "close", + "tags" : [ "cancel", "close", "exit", "stop", "x" ] +}, { + "name" : "refresh", + "tags" : [ "around", "arrow", "arrows", "direction", "inprogress", "load", "loading refresh", "navigation", "refresh", "renew", "right", "rotate", "turn" ] +}, { + "name" : "menu", + "tags" : [ "app", "application", "components", "hamburger", "interface", "line", "lines", "menu", "screen", "site", "ui", "ux", "web", "website" ] +}, { + "name" : "show_chart", + "tags" : [ "analytics", "bar", "bars", "chart", "data", "diagram", "graph", "infographic", "line", "measure", "metrics", "presentation", "show chart", "statistics", "tracking" ] +}, { + "name" : "multiline_chart", + "tags" : [ "analytics", "bar", "bars", "chart", "data", "diagram", "graph", "infographic", "line", "measure", "metrics", "multiple", "statistics", "tracking" ] +}, { + "name" : "pie_chart", + "tags" : [ "analytics", "bar", "bars", "chart", "data", "diagram", "graph", "infographic", "measure", "metrics", "pie", "statistics", "tracking" ] +}, { + "name" : "insert_chart", + "tags" : [ "analytics", "bar", "bars", "chart", "data", "diagram", "graph", "infographic", "insert", "measure", "metrics", "statistics", "tracking" ] +}, { + "name" : "people", + "tags" : [ "accounts", "committee", "face", "family", "friends", "humans", "network", "people", "persons", "profiles", "social", "team", "users" ] +}, { + "name" : "person", + "tags" : [ "account", "face", "human", "people", "person", "profile", "user" ] +}, { + "name" : "domain", + "tags" : [ "apartment", "architecture", "building", "business", "domain", "estate", "home", "place", "real", "residence", "residential", "shelter", "web", "www" ] +}, { + "name" : "devices_other", + "tags" : [ "Android", "OS", "ar", "cell", "chrome", "desktop", "device", "gadget", "hardware", "iOS", "ipad", "mac", "mobile", "monitor", "other", "phone", "tablet", "vr", "watch", "wearables", "window" ] +}, { + "name" : "widgets", + "tags" : [ "app", "box", "menu", "setting", "squares", "ui", "widgets" ] +}, { + "name" : "dashboard", + "tags" : [ "cards", "dashboard", "format", "layout", "rectangle", "shapes", "square", "web", "website" ] +}, { + "name" : "map", + "tags" : [ "destination", "direction", "location", "map", "maps", "pin", "place", "route", "stop", "travel" ] +}, { + "name" : "pin_drop", + "tags" : [ "destination", "direction", "drop", "location", "maps", "navigation", "pin", "place", "stop" ] +}, { + "name" : "gps_fixed", + "tags" : [ "destination", "direction", "fixed", "gps", "location", "maps", "pin", "place", "pointer", "stop", "tracking" ] +}, { + "name" : "extension", + "tags" : [ "app", "extended", "extension", "game", "jigsaw", "plugin add", "puzzle", "shape" ] +}, { + "name" : "search", + "tags" : [ "filter", "find", "glass", "look", "magnify", "magnifying", "search", "see" ] +}, { + "name" : "settings", + "tags" : [ "application", "change", "details", "gear", "info", "information", "options", "personal", "service", "settings" ] +}, { + "name" : "notifications", + "tags" : [ "active", "alarm", "alert", "bell", "chime", "notifications", "notify", "reminder", "ring", "sound" ] +}, { + "name" : "notifications_active", + "tags" : [ "active", "alarm", "alert", "bell", "chime", "notifications", "notify", "reminder", "ring", "ringing", "sound" ] +}, { + "name" : "info", + "tags" : [ "alert", "announcement", "assistance", "details", "help", "i", "info", "information", "service", "support" ] +}, { + "name" : "error_outline", + "tags" : [ "!", "alert", "attention", "caution", "circle", "danger", "error", "exclamation", "important", "mark", "notification", "outline", "symbol", "warning" ] +}, { + "name" : "warning", + "tags" : [ "!", "alert", "attention", "caution", "danger", "error", "exclamation", "important", "mark", "notification", "symbol", "triangle", "warning" ] +}, { + "name" : "list", + "tags" : [ "file", "format", "index", "list", "menu", "options" ] +}, { + "name" : "download", + "tags" : [ "arrow", "down", "download", "downloads", "drive", "install", "upload" ] +}, { + "name" : "import_export", + "tags" : [ "arrow", "arrows", "direction", "down", "explort", "import", "up" ] +}, { + "name" : "share", + "tags" : [ "DISABLE_IOS", "android", "connect", "contect", "disable_ios", "link", "media", "multimedia", "multiple", "network", "options", "share", "shared", "sharing", "social" ] +}, { + "name" : "add", + "tags" : [ "+", "add", "new symbol", "plus", "symbol" ] +}, { + "name" : "edit", + "tags" : [ "compose", "create", "edit", "editing", "input", "new", "pen", "pencil", "write", "writing" ] +}, { + "name" : "check", + "tags" : [ "DISABLE_IOS", "check", "confirm", "correct", "disable_ios", "done", "enter", "mark", "ok", "okay", "select", "tick", "yes" ] +}, { + "name" : "delete", + "tags" : [ "bin", "can", "delete", "garbage", "remove", "trash" ] +}, { + "name" : "thermostat", + "tags" : [ "climate", "forecast", "temperature", "thermostat", "weather" ] +}, { + "name" : "air", + "tags" : [ "air", "blowing", "breeze", "flow", "wave", "weather", "wind" ] +}, { + "name" : "lightbulb", + "tags" : [ "alert", "announcement", "idea", "info", "information", "light", "lightbulb" ] +}, { + "name" : "home", + "tags" : [ "address", "app", "application--house", "architecture", "building", "components", "design", "estate", "home", "interface", "layout", "place", "real", "residence", "residential", "screen", "shelter", "site", "structure", "ui", "unit", "ux", "web", "website", "window" ] +}, { + "name" : "account_circle", + "tags" : [ "account", "avatar", "circle", "face", "human", "people", "person", "profile", "thumbnail", "user" ] +}, { + "name" : "done", + "tags" : [ "DISABLE_IOS", "approve", "check", "complete", "disable_ios", "done", "mark", "ok", "select", "tick", "validate", "verified", "yes" ] +}, { + "name" : "check_circle", + "tags" : [ "approve", "check", "circle", "complete", "done", "mark", "ok", "select", "tick", "validate", "verified", "yes" ] +}, { + "name" : "expand_more", + "tags" : [ "arrow", "arrows", "chevron", "collapse", "direction", "down", "expand", "expandable", "list", "more" ] +}, { + "name" : "shopping_cart", + "tags" : [ "add", "bill", "buy", "card", "cart", "cash", "checkout", "coin", "commerce", "credit", "currency", "dollars", "money", "online", "pay", "payment", "shopping" ] +}, { + "name" : "email", + "tags" : [ "email", "envelop", "letter", "mail", "message", "send" ] +}, { + "name" : "favorite", + "tags" : [ "appreciate", "favorite", "heart", "like", "love", "remember", "save", "shape" ] +}, { + "name" : "description", + "tags" : [ "article", "data", "description", "doc", "document", "drive", "file", "folder", "folders", "notes", "page", "paper", "sheet", "slide", "text", "writing" ] +}, { + "name" : "logout", + "tags" : [ "app", "application", "arrow", "components", "design", "exit", "interface", "leave", "log", "login", "logout", "right", "screen", "site", "ui", "ux", "web", "website" ] +}, { + "name" : "favorite_border", + "tags" : [ "border", "favorite", "heart", "like", "love", "outline", "remember", "save", "shape" ] +}, { + "name" : "chevron_right", + "tags" : [ "arrow", "arrows", "chevron", "direction", "right" ] +}, { + "name" : "lock", + "tags" : [ "lock", "locked", "password", "privacy", "private", "protection", "safety", "secure", "security" ] +}, { + "name" : "location_on", + "tags" : [ "destination", "direction", "location", "maps", "on", "pin", "place", "room", "stop" ] +}, { + "name" : "schedule", + "tags" : [ "clock", "date", "schedule", "time" ] +}, { + "name" : "local_shipping", + "tags" : [ "automobile", "car", "cars", "delivery", "letter", "local", "mail", "maps", "office", "package", "parcel", "post", "postal", "send", "shipping", "shopping", "stamp", "transportation", "truck", "vehicle" ] +}, { + "name" : "language", + "tags" : [ "globe", "internet", "language", "planet", "website", "world", "www" ] +}, { + "name" : "call", + "tags" : [ "call", "cell", "contact", "device", "hardware", "mobile", "phone", "telephone" ] +}, { + "name" : "file_download", + "tags" : [ "arrow", "arrows", "down", "download", "downloads", "drive", "export", "file", "install", "upload" ] +}, { + "name" : "arrow_forward_ios", + "tags" : [ "app", "application", "arrow", "chevron", "components", "direction", "forward", "interface", "ios", "navigation", "next", "right", "screen", "site", "ui", "ux", "web", "website" ] +}, { + "name" : "arrow_back_ios", + "tags" : [ "DISABLE_IOS", "app", "application", "arrow", "back", "chevron", "components", "direction", "disable_ios", "interface", "ios", "left", "navigation", "previous", "screen", "site", "ui", "ux", "web", "website" ] +}, { + "name" : "groups", + "tags" : [ "body", "club", "collaboration", "crowd", "gathering", "groups", "human", "meeting", "people", "person", "social", "teams" ] +}, { + "name" : "cancel", + "tags" : [ "cancel", "circle", "close", "exit", "stop", "x" ] +}, { + "name" : "help_outline", + "tags" : [ "?", "assistance", "circle", "help", "info", "information", "outline", "punctuation", "question mark", "recent", "restore", "shape", "support", "symbol" ] +}, { + "name" : "arrow_drop_down", + "tags" : [ "app", "application", "arrow", "components", "direction", "down", "drop", "interface", "navigation", "screen", "site", "ui", "ux", "web", "website" ] +}, { + "name" : "face", + "tags" : [ "account", "emoji", "eyes", "face", "human", "lock", "log", "login", "logout", "people", "person", "profile", "recognition", "security", "social", "thumbnail", "unlock", "user" ] +}, { + "name" : "manage_accounts", + "tags" : [ "accounts", "change", "details service-human", "face", "gear", "manage", "options", "people", "person", "profile", "settings", "user" ] +}, { + "name" : "place", + "tags" : [ "destination", "direction", "location", "maps", "navigation", "pin", "place", "point", "stop" ] +}, { + "name" : "verified", + "tags" : [ "approve", "badge", "burst", "check", "complete", "done", "mark", "ok", "select", "star", "tick", "validate", "verified", "yes" ] +}, { + "name" : "add_circle_outline", + "tags" : [ "+", "add", "circle", "create", "new", "outline", "plus" ] +}, { + "name" : "filter_alt", + "tags" : [ "alt", "edit", "filter", "funnel", "options", "refine", "sift" ] +}, { + "name" : "thumb_up", + "tags" : [ "favorite", "fingers", "gesture", "hand", "hands", "like", "rank", "ranking", "rate", "rating", "thumb", "up" ] +}, { + "name" : "event", + "tags" : [ "calendar", "date", "day", "event", "mark", "month", "range", "remember", "reminder", "today", "week" ] +}, { + "name" : "star", + "tags" : [ "best", "bookmark", "favorite", "highlight", "ranking", "rate", "rating", "save", "star", "toggle" ] +}, { + "name" : "fingerprint", + "tags" : [ "finger", "fingerprint", "id", "identification", "identity", "print", "reader", "thumbprint", "verification" ] +}, { + "name" : "content_copy", + "tags" : [ "content", "copy", "cut", "doc", "document", "duplicate", "file", "multiple", "past" ] +}, { + "name" : "login", + "tags" : [ "access", "app", "application", "arrow", "components", "design", "enter", "in", "interface", "left", "log", "login", "screen", "sign", "site", "ui", "ux", "web", "website" ] +}, { + "name" : "add_circle", + "tags" : [ "+", "add", "circle", "create", "new", "plus" ] +}, { + "name" : "visibility_off", + "tags" : [ "disabled", "enabled", "eye", "off", "on", "reveal", "see", "show", "slash", "view", "visibility" ] +}, { + "name" : "check_circle_outline", + "tags" : [ "approve", "check", "circle", "complete", "done", "finished", "mark", "ok", "outline", "select", "tick", "validate", "verified", "yes" ] +}, { + "name" : "chevron_left", + "tags" : [ "DISABLE_IOS", "arrow", "arrows", "chevron", "direction", "disable_ios", "left" ] +}, { + "name" : "calendar_today", + "tags" : [ "calendar", "date", "day", "event", "month", "schedule", "today" ] +}, { + "name" : "send", + "tags" : [ "email", "mail", "message", "paper", "plane", "reply", "right", "send", "share" ] +}, { + "name" : "check_box", + "tags" : [ "approved", "box", "button", "check", "component", "control", "form", "mark", "ok", "select", "selected", "selection", "tick", "toggle", "ui", "yes" ] +}, { + "name" : "highlight_off", + "tags" : [ "cancel", "close", "exit", "highlight", "no", "off", "quit", "remove", "stop", "x" ] +}, { + "name" : "navigate_next", + "tags" : [ "arrow", "arrows", "direction", "navigate", "next", "right" ] +}, { + "name" : "help", + "tags" : [ "?", "assistance", "circle", "help", "info", "information", "punctuation", "question mark", "recent", "restore", "shape", "support", "symbol" ] +}, { + "name" : "phone", + "tags" : [ "call", "cell", "contact", "device", "hardware", "mobile", "phone", "telephone" ] +}, { + "name" : "paid", + "tags" : [ "circle", "currency", "money", "paid", "payment", "transaction" ] +}, { + "name" : "task_alt", + "tags" : [ "approve", "check", "circle", "complete", "done", "mark", "ok", "select", "task", "tick", "validate", "verified", "yes" ] +}, { + "name" : "question_answer", + "tags" : [ "answer", "bubble", "chat", "comment", "communicate", "conversation", "feedback", "message", "question", "speech", "talk" ] +}, { + "name" : "expand_less", + "tags" : [ "arrow", "arrows", "chevron", "collapse", "direction", "expand", "expandable", "less", "list", "up" ] +}, { + "name" : "clear", + "tags" : [ "back", "cancel", "clear", "correct", "delete", "erase", "exit", "x" ] +}, { + "name" : "date_range", + "tags" : [ "calendar", "date", "day", "event", "month", "range", "remember", "reminder", "schedule", "time", "today", "week" ] +}, { + "name" : "article", + "tags" : [ "article", "doc", "document", "file", "page", "paper", "text", "writing" ] +}, { + "name" : "error", + "tags" : [ "!", "alert", "attention", "caution", "circle", "danger", "error", "exclamation", "important", "mark", "notification", "symbol", "warning" ] +}, { + "name" : "photo_camera", + "tags" : [ "camera", "image", "photo", "photography", "picture" ] +}, { + "name" : "check_box_outline_blank", + "tags" : [ "blank", "box", "button", "check", "component", "control", "deselected", "empty", "form", "outline", "select", "selection", "square", "tick", "toggle", "ui" ] +}, { + "name" : "image", + "tags" : [ "disabled", "enabled", "hide", "image", "landscape", "mountain", "mountains", "off", "on", "photo", "photography", "picture", "slash" ] +}, { + "name" : "shopping_bag", + "tags" : [ "bag", "bill", "business", "buy", "card", "cart", "cash", "coin", "commerce", "credit", "currency", "dollars", "money", "online", "pay", "payment", "shop", "shopping", "store", "storefront" ] +}, { + "name" : "person_outline", + "tags" : [ "account", "face", "human", "outline", "people", "person", "profile", "user" ] +}, { + "name" : "school", + "tags" : [ "academy", "achievement", "cap", "class", "college", "education", "graduation", "hat", "knowledge", "learning", "school", "university" ] +}, { + "name" : "file_upload", + "tags" : [ "arrow", "arrows", "download", "drive", "export", "file", "up", "upload" ] +}, { + "name" : "perm_identity", + "tags" : [ "account", "avatar", "face", "human", "identity", "people", "perm", "person", "profile", "thumbnail", "user" ] +}, { + "name" : "credit_card", + "tags" : [ "bill", "card", "cash", "coin", "commerce", "cost", "credit", "currency", "dollars", "finance", "money", "online", "pay", "payment", "price", "shopping", "symbol" ] +}, { + "name" : "history", + "tags" : [ "arrow", "back", "backwards", "clock", "date", "history", "refresh", "renew", "reverse", "rotate", "schedule", "time", "turn" ] +}, { + "name" : "trending_up", + "tags" : [ "analytics", "arrow", "data", "diagram", "graph", "infographic", "measure", "metrics", "movement", "rate", "rating", "statistics", "tracking", "trending", "up" ] +}, { + "name" : "support_agent", + "tags" : [ "agent", "care", "customer", "face", "headphone", "person", "representative", "service", "support" ] +}, { + "name" : "account_balance", + "tags" : [ "account", "balance", "bank", "bill", "card", "cash", "coin", "commerce", "credit", "currency", "dollars", "finance", "money", "online", "pay", "payment" ] +}, { + "name" : "delete_outline", + "tags" : [ "bin", "can", "delete", "garbage", "outline", "remove", "trash" ] +}, { + "name" : "attach_money", + "tags" : [ "attach", "attachment", "bill", "card", "cash", "coin", "commerce", "cost", "credit", "currency", "dollars", "finance", "money", "online", "pay", "payment", "symbol" ] +}, { + "name" : "person_add", + "tags" : [ "+", "account", "add", "avatar", "face", "human", "new", "people", "person", "plus", "profile", "symbol", "user" ] +}, { + "name" : "public", + "tags" : [ "earth", "global", "globe", "map", "network", "planet", "public", "social", "space", "web", "world" ] +}, { + "name" : "save", + "tags" : [ "data", "disk", "document", "drive", "file", "floppy", "multimedia", "save", "storage" ] +}, { + "name" : "mail", + "tags" : [ "email", "envelop", "letter", "mail", "message", "send" ] +}, { + "name" : "report_problem", + "tags" : [ "!", "alert", "attention", "caution", "danger", "error", "exclamation", "feedback", "important", "mark", "notification", "problem", "report", "symbol", "triangle", "warning" ] +}, { + "name" : "fact_check", + "tags" : [ "approve", "check", "complete", "done", "fact", "list", "mark", "ok", "select", "tick", "validate", "verified", "yes" ] +}, { + "name" : "radio_button_unchecked", + "tags" : [ "bullet", "button", "circle", "deselected", "form", "off", "on", "point", "radio", "record", "select", "toggle", "unchecked" ] +}, { + "name" : "verified_user", + "tags" : [ "approve", "certified", "check", "complete", "done", "mark", "ok", "privacy", "private", "protect", "protection", "security", "select", "shield", "tick", "user", "validate", "verified", "yes" ] +}, { + "name" : "assignment", + "tags" : [ "assignment", "clipboard", "doc", "document", "text", "writing" ] +}, { + "name" : "link", + "tags" : [ "chain", "clip", "connection", "link", "linked", "links", "multimedia", "url" ] +}, { + "name" : "play_circle_filled", + "tags" : [ "arrow", "circle", "control", "controls", "media", "music", "play", "video" ] +}, { + "name" : "emoji_events", + "tags" : [ "achievement", "award", "chalice", "champion", "cup", "emoji", "events", "first", "prize", "reward", "sport", "trophy", "winner" ] +}, { + "name" : "remove", + "tags" : [ "can", "delete", "minus", "negative", "remove", "substract", "trash" ] +}, { + "name" : "star_rate", + "tags" : [ "achievement", "bookmark", "favorite", "highlight", "important", "marked", "ranking", "rate", "rating rank", "reward", "save", "saved", "shape", "special", "star" ] +}, { + "name" : "apps", + "tags" : [ "all", "applications", "apps", "circles", "collection", "components", "dots", "grid", "interface", "squares", "ui", "ux" ] +}, { + "name" : "business", + "tags" : [ "apartment", "architecture", "building", "business", "company", "estate", "home", "place", "real", "residence", "residential", "shelter" ] +}, { + "name" : "filter_list", + "tags" : [ "filter", "lines", "list", "organize", "sort" ] +}, { + "name" : "arrow_right_alt", + "tags" : [ "alt", "arrow", "arrows", "direction", "east", "navigation", "pointing", "right" ] +}, { + "name" : "chat", + "tags" : [ "bubble", "chat", "comment", "communicate", "feedback", "message", "speech" ] +}, { + "name" : "account_balance_wallet", + "tags" : [ "account", "balance", "bank", "bill", "card", "cash", "coin", "commerce", "credit", "currency", "dollars", "finance", "money", "online", "pay", "payment", "wallet" ] +}, { + "name" : "payments", + "tags" : [ "bill", "card", "cash", "coin", "commerce", "cost", "credit", "currency", "dollars", "finance", "layer", "money", "multiple", "online", "pay", "payment", "payments", "price", "shopping", "symbol" ] +}, { + "name" : "menu_book", + "tags" : [ "book", "dining", "food", "meal", "menu", "restaurant" ] +}, { + "name" : "folder", + "tags" : [ "data", "doc", "document", "drive", "file", "folder", "folders", "sheet", "slide", "storage" ] +}, { + "name" : "keyboard_arrow_down", + "tags" : [ "arrow", "arrows", "down", "keyboard" ] +}, { + "name" : "autorenew", + "tags" : [ "around", "arrow", "arrows", "autorenew", "cache", "cached", "direction", "inprogress", "load", "loading refresh", "navigation", "renew", "rotate", "turn" ] +}, { + "name" : "build", + "tags" : [ "adjust", "build", "fix", "home", "nest", "repair", "tool", "tools", "wrench" ] +}, { + "name" : "videocam", + "tags" : [ "cam", "camera", "conference", "film", "filming", "hardware", "image", "motion", "picture", "video", "videography" ] +}, { + "name" : "view_list", + "tags" : [ "design", "format", "grid", "layout", "lines", "list", "stacked", "view", "website" ] +}, { + "name" : "print", + "tags" : [ "draft", "fax", "ink", "machine", "office", "paper", "print", "printer", "send" ] +}, { + "name" : "work", + "tags" : [ "bag", "baggage", "briefcase", "business", "case", "job", "suitcase", "work" ] +}, { + "name" : "store", + "tags" : [ "bill", "building", "business", "card", "cash", "coin", "commerce", "company", "credit", "currency", "dollars", "market", "money", "online", "pay", "payment", "shop", "shopping", "store", "storefront" ] +}, { + "name" : "analytics", + "tags" : [ "analytics", "assessment", "bar", "chart", "data", "diagram", "graph", "infographic", "measure", "metrics", "statistics", "tracking" ] +}, { + "name" : "radio_button_checked", + "tags" : [ "app", "application", "bullet", "button", "checked", "circle", "components", "design", "form", "interface", "off", "on", "point", "radio", "record", "screen", "select", "selected", "site", "toggle", "ui", "ux", "web", "website" ] +}, { + "name" : "phone_iphone", + "tags" : [ "Android", "OS", "cell", "device", "hardware", "iOS", "iphone", "mobile", "phone", "tablet" ] +}, { + "name" : "play_circle", + "tags" : [ "arrow", "circle", "control", "controls", "media", "music", "play", "video" ] +}, { + "name" : "tune", + "tags" : [ "adjust", "audio", "controls", "custom", "customize", "edit", "editing", "filter", "filters", "instant", "mix", "music", "options", "setting", "settings", "slider", "sliders", "switches", "tune" ] +}, { + "name" : "delete_forever", + "tags" : [ "bin", "can", "cancel", "delete", "exit", "forever", "garbage", "remove", "trash", "x" ] +}, { + "name" : "today", + "tags" : [ "calendar", "date", "day", "event", "mark", "month", "remember", "reminder", "schedule", "time", "today" ] +}, { + "name" : "grid_view", + "tags" : [ "app", "application square", "blocks", "components", "dashboard", "design", "grid", "interface", "layout", "screen", "site", "tiles", "ui", "ux", "view", "web", "website", "window" ] +}, { + "name" : "east", + "tags" : [ "arrow", "directional", "east", "maps", "navigation", "right" ] +}, { + "name" : "inventory_2", + "tags" : [ "archive", "box", "file", "inventory", "organize", "packages", "product", "stock", "storage", "supply" ] +}, { + "name" : "mail_outline", + "tags" : [ "email", "envelop", "letter", "mail", "message", "outline", "send" ] +}, { + "name" : "admin_panel_settings", + "tags" : [ "account", "admin", "avatar", "certified", "face", "human", "panel", "people", "person", "privacy", "private", "profile", "protect", "protection", "security", "settings", "shield", "user", "verified" ] +}, { + "name" : "mic", + "tags" : [ "hear", "hearing", "mic", "microphone", "noise", "record", "sound", "voice" ] +}, { + "name" : "calendar_month", + "tags" : [ "calendar", "date", "day", "event", "month", "schedule", "today" ] +}, { + "name" : "group", + "tags" : [ "accounts", "committee", "face", "family", "friends", "group", "humans", "network", "people", "persons", "profiles", "social", "team", "users" ] +}, { + "name" : "picture_as_pdf", + "tags" : [ "alphabet", "as", "character", "document", "file", "font", "image", "letter", "multiple", "pdf", "photo", "photography", "picture", "symbol", "text", "type" ] +}, { + "name" : "lock_open", + "tags" : [ "lock", "open", "password", "privacy", "private", "protection", "safety", "secure", "security", "unlocked" ] +}, { + "name" : "volume_up", + "tags" : [ "audio", "control", "music", "sound", "speaker", "tv", "up", "volume" ] +}, { + "name" : "watch_later", + "tags" : [ "clock", "date", "later", "schedule", "time", "watch" ] +}, { + "name" : "grade", + "tags" : [ "'favorite_news' .", "'star_outline'", "Duplicate of 'star_boarder'", "star_border_purple500'" ] +}, { + "name" : "receipt_long", + "tags" : [ "bill", "check", "document", "list", "long", "paper", "paperwork", "receipt", "record", "store", "transaction" ] +}, { + "name" : "local_offer", + "tags" : [ "deal", "discount", "offer", "price", "shop", "shopping", "store", "tag" ] +}, { + "name" : "room", + "tags" : [ "destination", "direction", "location", "maps", "pin", "place", "room", "stop" ] +}, { + "name" : "update", + "tags" : [ "arrow", "back", "backwards", "clock", "forward", "history", "load", "refresh", "reverse", "schedule", "time", "update" ] +}, { + "name" : "badge", + "tags" : [ "account", "avatar", "badge", "card", "certified", "employee", "face", "human", "identification", "name", "people", "person", "profile", "security", "user", "work" ] +}, { + "name" : "savings", + "tags" : [ "bank", "bill", "card", "cash", "coin", "commerce", "cost", "credit", "currency", "dollars", "finance", "money", "online", "pay", "payment", "pig", "piggy", "savings", "symbol" ] +}, { + "name" : "code", + "tags" : [ "brackets", "code", "css", "develop", "developer", "engineer", "engineering", "html", "platform" ] +}, { + "name" : "light_mode", + "tags" : [ "bright", "brightness", "day", "device", "light", "lighting", "mode", "morning", "sky", "sun", "sunny" ] +}, { + "name" : "receipt", + "tags" : [ ] +}, { + "name" : "circle", + "tags" : [ "circle", "full", "geometry", "moon" ] +}, { + "name" : "inventory", + "tags" : [ "archive", "box", "clipboard", "doc", "document", "file", "inventory", "organize", "packages", "product", "stock", "supply" ] +}, { + "name" : "add_shopping_cart", + "tags" : [ "add", "card", "cart", "cash", "checkout", "coin", "commerce", "credit", "currency", "dollars", "money", "online", "pay", "payment", "plus", "shopping" ] +}, { + "name" : "contact_support", + "tags" : [ "?", "bubble", "chat", "comment", "communicate", "contact", "help", "info", "information", "mark", "message", "punctuation", "question", "question mark", "speech", "support", "symbol" ] +}, { + "name" : "category", + "tags" : [ "categories", "category", "circle", "collection", "items", "product", "sort", "square", "triangle" ] +}, { + "name" : "edit_note", + "tags" : [ "compose", "create", "draft", "edit", "editing", "input", "lines", "note", "pen", "pencil", "text", "write", "writing" ] +}, { + "name" : "insights", + "tags" : [ "ai", "analytics", "artificial", "automatic", "automation", "bar", "bars", "chart", "custom", "data", "diagram", "genai", "graph", "infographic", "insights", "intelligence", "magic", "measure", "metrics", "smart", "spark", "sparkle", "star", "stars", "statistics", "tracking" ] +}, { + "name" : "power_settings_new", + "tags" : [ "info", "information", "off", "on", "power", "save", "settings", "shutdown" ] +}, { + "name" : "campaign", + "tags" : [ "alert", "announcement", "campaign", "loud", "megaphone", "microphone", "notification", "speaker" ] +}, { + "name" : "format_list_bulleted", + "tags" : [ "align", "alignment", "bulleted", "doc", "edit", "editing", "editor", "format", "list", "notes", "sheet", "spreadsheet", "text", "type", "writing" ] +}, { + "name" : "star_border", + "tags" : [ "best", "bookmark", "border", "favorite", "highlight", "outline", "ranking", "rate", "rating", "save", "star", "toggle" ] +}, { + "name" : "pause", + "tags" : [ "control", "controls", "media", "music", "pause", "video" ] +}, { + "name" : "remove_circle_outline", + "tags" : [ "block", "can", "circle", "delete", "minus", "negative", "outline", "remove", "substract", "trash" ] +}, { + "name" : "warning_amber", + "tags" : [ "!", "alert", "amber", "attention", "caution", "danger", "error", "exclamation", "important", "mark", "notification", "symbol", "triangle", "warning" ] +}, { + "name" : "wifi", + "tags" : [ "connection", "data", "internet", "network", "scan", "service", "signal", "wifi", "wireless" ] +}, { + "name" : "arrow_back_ios_new", + "tags" : [ "DISABLE_IOS", "app", "application", "arrow", "back", "chevron", "components", "direction", "disable_ios", "interface", "ios", "left", "navigation", "new", "previous", "screen", "site", "ui", "ux", "web", "website" ] +}, { + "name" : "restart_alt", + "tags" : [ "alt", "around", "arrow", "inprogress", "load", "loading refresh", "reboot", "renew", "repeat", "reset", "restart" ] +}, { + "name" : "done_all", + "tags" : [ "all", "approve", "check", "complete", "done", "layers", "mark", "multiple", "ok", "select", "stack", "tick", "validate", "verified", "yes" ] +}, { + "name" : "pets", + "tags" : [ "animal", "cat", "dog", "hand", "paw", "pet" ] +}, { + "name" : "storefront", + "tags" : [ "business", "buy", "cafe", "commerce", "front", "market", "places", "restaurant", "retail", "sell", "shop", "shopping", "store", "storefront" ] +}, { + "name" : "sort", + "tags" : [ "filter", "find", "lines", "list", "organize", "sort" ] +}, { + "name" : "mode_edit", + "tags" : [ "compose", "create", "draft", "draw", "edit", "mode", "pen", "pencil", "write" ] +}, { + "name" : "list_alt", + "tags" : [ "alt", "box", "contained", "format", "lines", "list", "order", "reorder", "stacked", "title" ] +}, { + "name" : "toggle_on", + "tags" : [ "active", "app", "application", "components", "configuration", "control", "design", "disable", "inable", "inactive", "interface", "off", "on", "selection", "settings", "site", "slider", "switch", "toggle", "ui", "ux", "web", "website" ] +}, { + "name" : "dark_mode", + "tags" : [ "app", "application", "dark", "device", "interface", "mode", "moon", "night", "silent", "theme", "ui", "ux", "website" ] +}, { + "name" : "engineering", + "tags" : [ "body", "cogs", "cogwheel", "construction", "engineering", "fixing", "gears", "hat", "helmet", "human", "maintenance", "people", "person", "setting", "worker" ] +}, { + "name" : "explore", + "tags" : [ "compass", "destination", "direction", "east", "explore", "location", "maps", "needle", "north", "south", "travel", "west" ] +}, { + "name" : "bolt", + "tags" : [ "bolt", "electric", "energy", "fast", "flash", "lightning", "power", "thunderbolt" ] +}, { + "name" : "construction", + "tags" : [ "build", "carpenter", "construction", "equipment", "fix", "hammer", "improvement", "industrial", "industry", "repair", "tools", "wrench" ] +}, { + "name" : "qr_code_scanner", + "tags" : [ "barcode", "camera", "code", "media", "product", "qr", "quick", "response", "scanner", "smartphone", "url", "urls" ] +}, { + "name" : "bookmark", + "tags" : [ "archive", "bookmark", "favorite", "label", "library", "read", "reading", "remember", "ribbon", "save", "tag" ] +}, { + "name" : "vpn_key", + "tags" : [ "code", "key", "lock", "network", "passcode", "password", "unlock", "vpn" ] +}, { + "name" : "monetization_on", + "tags" : [ "bill", "card", "cash", "circle", "coin", "commerce", "cost", "credit", "currency", "dollars", "finance", "monetization", "money", "on", "online", "pay", "payment", "shopping", "symbol" ] +}, { + "name" : "attach_file", + "tags" : [ "add", "attach", "attachment", "clip", "file", "link", "mail", "media" ] +}, { + "name" : "timer", + "tags" : [ "alarm", "alert", "bell", "clock", "disabled", "duration", "enabled", "notification", "off", "on", "slash", "stop", "time", "timer", "watch" ] +}, { + "name" : "account_box", + "tags" : [ "account", "avatar", "box", "face", "human", "people", "person", "profile", "square", "thumbnail", "user" ] +}, { + "name" : "note_add", + "tags" : [ "+", "-doc", "add", "data", "document", "drive", "file", "folder", "folders", "new", "note", "page", "paper", "plus", "sheet", "slide", "symbol", "writing" ] +}, { + "name" : "reorder", + "tags" : [ "format", "lines", "list", "order", "reorder", "stacked" ] +}, { + "name" : "bookmark_border", + "tags" : [ "archive", "bookmark", "border", "favorite", "label", "library", "read", "reading", "remember", "ribbon", "save", "tag" ] +}, { + "name" : "arrow_right", + "tags" : [ "app", "application", "arrow", "components", "direction", "interface", "navigation", "right", "screen", "site", "ui", "ux", "web", "website" ] +}, { + "name" : "pending_actions", + "tags" : [ "actions", "clipboard", "clock", "date", "doc", "document", "pending", "remember", "schedule", "time" ] +}, { + "name" : "smartphone", + "tags" : [ "Android", "OS", "call", "cell", "chat", "device", "hardware", "iOS", "mobile", "phone", "smartphone", "tablet", "text" ] +}, { + "name" : "upload_file", + "tags" : [ "arrow", "data", "doc", "document", "download", "drive", "file", "folder", "folders", "page", "paper", "sheet", "slide", "up", "upload", "writing" ] +}, { + "name" : "account_tree", + "tags" : [ "account", "analytics", "chart", "connect", "data", "diagram", "flow", "graph", "infographic", "measure", "metrics", "process", "square", "statistics", "structure", "tracking", "tree" ] +}, { + "name" : "shopping_basket", + "tags" : [ "add", "basket", "bill", "buy", "card", "cart", "cash", "checkout", "coin", "commerce", "credit", "currency", "dollars", "money", "online", "pay", "payment", "shopping" ] +}, { + "name" : "flag", + "tags" : [ "country", "flag", "goal", "mark", "nation", "report", "start" ] +}, { + "name" : "apartment", + "tags" : [ "accommodation", "apartment", "architecture", "building", "city", "company", "estate", "flat", "home", "house", "office", "places", "real", "residence", "residential", "shelter", "units", "workplace" ] +}, { + "name" : "restaurant", + "tags" : [ "breakfast", "dining", "dinner", "eat", "food", "fork", "knife", "local", "lunch", "meal", "places", "restaurant", "spoon", "utensils" ] +}, { + "name" : "people_alt", + "tags" : [ "accounts", "committee", "face", "family", "friends", "humans", "network", "people", "persons", "profiles", "social", "team", "users" ] +}, { + "name" : "reply", + "tags" : [ "arrow", "backward", "left", "mail", "message", "reply", "send", "share" ] +}, { + "name" : "play_circle_outline", + "tags" : [ "arrow", "circle", "control", "controls", "media", "music", "outline", "play", "video" ] +}, { + "name" : "payment", + "tags" : [ "bill", "card", "cash", "coin", "commerce", "cost", "credit", "currency", "dollars", "finance", "money", "online", "pay", "payment", "price", "shopping", "symbol" ] +}, { + "name" : "sync", + "tags" : [ "360", "around", "arrow", "arrows", "direction", "inprogress", "load", "loading refresh", "renew", "rotate", "sync", "turn" ] +}, { + "name" : "task", + "tags" : [ "approve", "check", "complete", "data", "doc", "document", "done", "drive", "file", "folder", "folders", "mark", "ok", "page", "paper", "select", "sheet", "slide", "task", "tick", "validate", "verified", "writing", "yes" ] +}, { + "name" : "launch", + "tags" : [ "app", "application", "arrow", "box", "components", "interface", "launch", "new", "open", "screen", "site", "ui", "ux", "web", "website", "window" ] +}, { + "name" : "menu_open", + "tags" : [ "app", "application", "arrow", "components", "hamburger", "interface", "left", "line", "lines", "menu", "open", "screen", "site", "ui", "ux", "web", "website" ] +}, { + "name" : "add_box", + "tags" : [ "add", "box", "new square", "plus", "symbol" ] +}, { + "name" : "drag_indicator", + "tags" : [ "app", "application", "circles", "components", "design", "dots", "drag", "drop", "indicator", "interface", "layout", "mobile", "monitor", "move", "phone", "screen", "shape", "shift", "site", "tablet", "ui", "ux", "web", "website", "window" ] +}, { + "name" : "supervisor_account", + "tags" : [ "account", "avatar", "control", "face", "human", "parental", "parental control", "parents", "people", "person", "profile", "supervised", "supervisor", "user" ] +}, { + "name" : "touch_app", + "tags" : [ "app", "command", "fingers", "gesture", "hand", "press", "tap", "touch" ] +}, { + "name" : "pending", + "tags" : [ "circle", "dots", "loading", "pending", "progress", "wait", "waiting" ] +}, { + "name" : "zoom_in", + "tags" : [ "big", "bigger", "find", "glass", "grow", "in", "look", "magnify", "magnifying", "plus", "scale", "search", "see", "size", "zoom" ] +}, { + "name" : "manage_search", + "tags" : [ "glass", "history", "magnifying", "manage", "search", "text" ] +}, { + "name" : "remove_circle", + "tags" : [ "block", "can", "circle", "delete", "minus", "negative", "remove", "substract", "trash" ] +}, { + "name" : "group_add", + "tags" : [ "accounts", "add", "committee", "face", "family", "friends", "group", "humans", "increase", "more", "network", "people", "persons", "plus", "profiles", "social", "team", "users" ] +}, { + "name" : "chat_bubble_outline", + "tags" : [ "bubble", "chat", "comment", "communicate", "feedback", "message", "outline", "speech" ] +}, { + "name" : "assessment", + "tags" : [ "analytics", "assessment", "bar", "chart", "data", "diagram", "graph", "infographic", "measure", "metrics", "statistics", "tracking" ] +}, { + "name" : "priority_high", + "tags" : [ "!", "alert", "attention", "caution", "danger", "error", "exclamation", "high", "important", "mark", "notification", "symbol", "warning" ] +}, { + "name" : "push_pin", + "tags" : [ "location", "marker", "pin", "place", "push", "remember", "save" ] +}, { + "name" : "feed", + "tags" : [ "article", "feed", "headline", "information", "news", "newspaper", "paper", "public", "social", "timeline" ] +}, { + "name" : "leaderboard", + "tags" : [ "analytics", "bar", "bars", "chart", "data", "diagram", "graph", "infographic", "leaderboard", "measure", "metrics", "statistics", "tracking" ] +}, { + "name" : "summarize", + "tags" : [ "doc", "document", "list", "menu", "note", "report", "summary" ] +}, { + "name" : "block", + "tags" : [ "avoid", "block", "cancel", "close", "entry", "exit", "no", "prohibited", "quit", "remove", "stop" ] +}, { + "name" : "event_available", + "tags" : [ "approve", "available", "calendar", "check", "complete", "date", "done", "event", "mark", "ok", "schedule", "select", "tick", "time", "validate", "verified", "yes" ] +}, { + "name" : "thumb_up_off_alt", + "tags" : [ "alt", "disabled", "enabled", "favorite", "fingers", "gesture", "hand", "hands", "like", "off", "offline", "on", "rank", "ranking", "rate", "rating", "slash", "thumb", "up" ] +}, { + "name" : "directions_car", + "tags" : [ "automobile", "car", "cars", "direction", "directions", "maps", "public", "transportation", "vehicle" ] +}, { + "name" : "open_in_full", + "tags" : [ "action", "arrow", "arrows", "expand", "full", "grow", "in", "move", "open" ] +}, { + "name" : "auto_stories", + "tags" : [ "auto", "book", "flipping", "pages", "stories" ] +}, { + "name" : "post_add", + "tags" : [ "+", "add", "data", "doc", "document", "drive", "file", "folder", "folders", "page", "paper", "plus", "post", "sheet", "slide", "text", "writing" ] +}, { + "name" : "calculate", + "tags" : [ "+", "-", "=", "calculate", "count", "finance calculator", "math" ] +}, { + "name" : "alternate_email", + "tags" : [ "@", "address", "alternate", "contact", "email", "tag" ] +}, { + "name" : "create", + "tags" : [ "compose", "create", "edit", "editing", "input", "new", "pen", "pencil", "write", "writing" ] +}, { + "name" : "cloud_upload", + "tags" : [ "app", "application", "arrow", "backup", "cloud", "connection", "download", "drive", "files", "folders", "internet", "network", "sky", "storage", "up", "upload" ] +}, { + "name" : "local_fire_department", + "tags" : [ "911", "climate", "department", "fire", "firefighter", "flame", "heat", "home", "hot", "nest", "thermostat" ] +}, { + "name" : "bar_chart", + "tags" : [ "analytics", "bar", "chart", "data", "diagram", "graph", "infographic", "measure", "metrics", "statistics", "tracking" ] +}, { + "name" : "password", + "tags" : [ "key", "login", "password", "pin", "security", "star", "unlock" ] +}, { + "name" : "collections", + "tags" : [ "album", "collections", "gallery", "image", "landscape", "library", "mountain", "mountains", "photo", "photography", "picture", "stack" ] +}, { + "name" : "preview", + "tags" : [ "design", "eye", "layout", "preview", "reveal", "screen", "see", "show", "site", "view", "web", "website", "window", "www" ] +}, { + "name" : "star_outline", + "tags" : [ "bookmark", "favorite", "half", "highlight", "ranking", "rate", "rating", "save", "star", "toggle" ] +}, { + "name" : "exit_to_app", + "tags" : [ "app", "application", "arrow", "components", "design", "exit", "export", "interface", "layout", "leave", "mobile", "monitor", "move", "output", "phone", "screen", "site", "tablet", "to", "ui", "ux", "web", "website", "window" ] +}, { + "name" : "done_outline", + "tags" : [ "all", "approve", "check", "complete", "done", "mark", "ok", "outline", "select", "tick", "validate", "verified", "yes" ] +}, { + "name" : "psychology", + "tags" : [ "behavior", "body", "brain", "cognitive", "function", "gear", "head", "human", "intellectual", "mental", "mind", "people", "person", "preferences", "psychiatric", "psychology", "science", "settings", "social", "therapy", "thinking", "thoughts" ] +}, { + "name" : "assignment_ind", + "tags" : [ "account", "assignment", "clipboard", "doc", "document", "face", "ind", "people", "person", "profile", "user" ] +}, { + "name" : "volunteer_activism", + "tags" : [ "activism", "donation", "fingers", "gesture", "giving", "hand", "hands", "heart", "love", "sharing", "volunteer" ] +}, { + "name" : "navigate_before", + "tags" : [ "arrow", "arrows", "before", "direction", "left", "navigate" ] +}, { + "name" : "published_with_changes", + "tags" : [ "approve", "arrow", "arrows", "changes", "check", "complete", "done", "inprogress", "load", "loading", "mark", "ok", "published", "refresh", "renew", "replace", "rotate", "select", "tick", "validate", "verified", "with", "yes" ] +}, { + "name" : "add_a_photo", + "tags" : [ "+", "a photo", "add", "camera", "lens", "new", "photography", "picture", "plus", "symbol" ] +}, { + "name" : "auto_awesome", + "tags" : [ "adjust", "ai", "artificial", "automatic", "automation", "custom", "edit", "editing", "enhance", "genai", "intelligence", "magic", "smart", "spark", "sparkle", "star", "stars" ] +}, { + "name" : "card_giftcard", + "tags" : [ "account", "balance", "bill", "card", "cart", "cash", "certificate", "coin", "commerce", "credit", "currency", "dollars", "gift", "giftcard", "money", "online", "pay", "payment", "present", "shopping" ] +}, { + "name" : "fullscreen", + "tags" : [ "adjust", "app", "application", "components", "full", "fullscreen", "interface", "screen", "site", "size", "ui", "ux", "view", "web", "website" ] +}, { + "name" : "sell", + "tags" : [ "bill", "card", "cart", "cash", "coin", "commerce", "credit", "currency", "dollars", "money", "online", "pay", "payment", "price", "sell", "shopping", "tag" ] +}, { + "name" : "checklist", + "tags" : [ "align", "alignment", "approve", "check", "checklist", "complete", "doc", "done", "edit", "editing", "editor", "format", "list", "mark", "notes", "ok", "select", "sheet", "spreadsheet", "text", "tick", "type", "validate", "verified", "writing", "yes" ] +}, { + "name" : "view_in_ar", + "tags" : [ "3d", "ar", "augmented", "cube", "daydream", "headset", "in", "reality", "square", "view", "vr" ] +}, { + "name" : "undo", + "tags" : [ "arrow", "backward", "mail", "previous", "redo", "repeat", "rotate", "undo" ] +}, { + "name" : "arrow_drop_up", + "tags" : [ "app", "application", "arrow", "components", "direction", "drop", "interface", "navigation", "screen", "site", "ui", "up", "ux", "web", "website" ] +}, { + "name" : "feedback", + "tags" : [ "!", "alert", "announcement", "attention", "bubble", "caution", "chat", "comment", "communicate", "danger", "error", "exclamation", "feedback", "important", "mark", "message", "notification", "speech", "symbol", "warning" ] +}, { + "name" : "health_and_safety", + "tags" : [ "+", "add", "and", "certified", "cross", "health", "home", "nest", "plus", "privacy", "private", "protect", "protection", "safety", "security", "shield", "symbol", "verified" ] +}, { + "name" : "work_outline", + "tags" : [ "bag", "baggage", "briefcase", "business", "case", "job", "suitcase", "work" ] +}, { + "name" : "unfold_more", + "tags" : [ "arrow", "arrows", "chevron", "collapse", "direction", "down", "expand", "expandable", "list", "more", "navigation", "unfold" ] +}, { + "name" : "travel_explore", + "tags" : [ "earth", "explore", "find", "glass", "global", "globe", "look", "magnify", "magnifying", "map", "network", "planet", "search", "see", "social", "space", "travel", "web", "world" ] +}, { + "name" : "palette", + "tags" : [ "art", "color", "colors", "filters", "paint", "palette" ] +}, { + "name" : "keyboard_arrow_right", + "tags" : [ "arrow", "arrows", "keyboard", "right" ] +}, { + "name" : "double_arrow", + "tags" : [ "arrow", "arrows", "direction", "double", "multiple", "navigation", "right" ] +}, { + "name" : "computer", + "tags" : [ "Android", "OS", "chrome", "computer", "desktop", "device", "hardware", "iOS", "mac", "monitor", "web", "window" ] +}, { + "name" : "timeline", + "tags" : [ "data", "history", "line", "movement", "point", "points", "timeline", "tracking", "trending", "zigzag" ] +}, { + "name" : "thumb_up_alt", + "tags" : [ "agreed", "approved", "confirm", "correct", "favorite", "feedback", "good", "happy", "like", "okay", "positive", "satisfaction", "social", "thumb", "up", "vote", "yes" ] +}, { + "name" : "signal_cellular_alt", + "tags" : [ "alt", "analytics", "bar", "cell", "cellular", "chart", "data", "diagram", "graph", "infographic", "internet", "measure", "metrics", "mobile", "network", "phone", "signal", "statistics", "tracking", "wifi", "wireless" ] +}, { + "name" : "replay", + "tags" : [ "arrow", "arrows", "control", "controls", "music", "refresh", "renew", "repeat", "replay", "video" ] +}, { + "name" : "swap_horiz", + "tags" : [ "arrow", "arrows", "back", "forward", "horizontal", "swap" ] +}, { + "name" : "volume_off", + "tags" : [ "audio", "control", "disabled", "enabled", "low", "music", "off", "on", "slash", "sound", "speaker", "tv", "volume" ] +}, { + "name" : "forum", + "tags" : [ "bubble", "chat", "comment", "communicate", "community", "conversation", "feedback", "forum", "hub", "message", "speech" ] +}, { + "name" : "skip_next", + "tags" : [ "arrow", "control", "controls", "music", "next", "play", "previous", "skip", "video" ] +}, { + "name" : "water_drop", + "tags" : [ "drink", "drop", "droplet", "eco", "liquid", "nature", "ocean", "rain", "social", "water" ] +}, { + "name" : "assignment_turned_in", + "tags" : [ "approve", "assignment", "check", "clipboard", "complete", "doc", "document", "done", "in", "mark", "ok", "select", "tick", "turn", "validate", "verified", "yes" ] +}, { + "name" : "library_books", + "tags" : [ "add", "album", "audio", "book", "books", "collection", "library", "read", "reading" ] +}, { + "name" : "maps_home_work", + "tags" : [ "building", "home", "house", "maps", "office", "work" ] +}, { + "name" : "dns", + "tags" : [ "address", "bars", "dns", "domain", "information", "ip", "list", "lookup", "name", "server", "system" ] +}, { + "name" : "sync_alt", + "tags" : [ "alt", "arrow", "arrows", "horizontal", "internet", "sync", "technology", "up", "update", "wifi" ] +}, { + "name" : "how_to_reg", + "tags" : [ "approve", "ballot", "check", "complete", "done", "election", "how", "mark", "ok", "poll", "register", "registration", "select", "tick", "to reg", "validate", "verified", "vote", "yes" ] +}, { + "name" : "notifications_none", + "tags" : [ "alarm", "alert", "bell", "none", "notifications", "notify", "reminder", "sound" ] +}, { + "name" : "stars", + "tags" : [ "achievement", "bookmark", "circle", "favorite", "highlight", "important", "marked", "ranking", "rate", "rating rank", "reward", "save", "saved", "shape", "special", "star" ] +}, { + "name" : "flight_takeoff", + "tags" : [ "airport", "departed", "departing", "flight", "fly", "landing", "plane", "takeoff", "transportation", "travel" ] +}, { + "name" : "label", + "tags" : [ "favorite", "indent", "label", "library", "mail", "remember", "save", "stamp", "sticker", "tag" ] +}, { + "name" : "devices", + "tags" : [ "Android", "OS", "computer", "desktop", "device", "hardware", "iOS", "laptop", "mobile", "monitor", "phone", "tablet", "watch", "wearable", "web" ] +}, { + "name" : "chat_bubble", + "tags" : [ "bubble", "chat", "comment", "communicate", "feedback", "message", "speech" ] +}, { + "name" : "emoji_emotions", + "tags" : [ "+", "add", "emoji", "emotions", "expressions", "face", "feelings", "glad", "happiness", "happy", "icon", "icons", "insert", "like", "mood", "new", "person", "pleased", "plus", "smile", "smiling", "social", "survey", "symbol" ] +}, { + "name" : "remove_red_eye", + "tags" : [ "eye", "iris", "look", "looking", "preview", "red", "remove", "see", "sight", "vision" ] +}, { + "name" : "content_paste", + "tags" : [ "clipboard", "content", "copy", "cut", "doc", "document", "file", "multiple", "past" ] +}, { + "name" : "folder_open", + "tags" : [ "data", "doc", "document", "drive", "file", "folder", "folders", "open", "sheet", "slide", "storage" ] +}, { + "name" : "text_snippet", + "tags" : [ "data", "doc", "document", "file", "note", "notes", "snippet", "storage", "text", "writing" ] +}, { + "name" : "tips_and_updates", + "tags" : [ "ai", "alert", "and", "announcement", "artificial", "automatic", "automation", "custom", "electricity", "genai", "idea", "info", "information", "intelligence", "light", "lightbulb", "magic", "smart", "spark", "sparkle", "star", "tips", "updates" ] +}, { + "name" : "my_location", + "tags" : [ "destination", "direction", "location", "maps", "navigation", "pin", "place", "point", "stop" ] +}, { + "name" : "textsms", + "tags" : [ "bubble", "chat", "comment", "communicate", "dots", "feedback", "message", "speech", "textsms" ] +}, { + "name" : "cloud", + "tags" : [ "cloud", "connection", "internet", "network", "sky", "upload" ] +}, { + "name" : "sports_esports", + "tags" : [ "controller", "entertainment", "esports", "game", "gamepad", "gaming", "hobby", "online", "social", "sports", "video" ] +}, { + "name" : "security", + "tags" : [ "certified", "privacy", "private", "protect", "protection", "security", "shield", "verified" ] +}, { + "name" : "request_quote", + "tags" : [ "bill", "card", "cash", "coin", "commerce", "cost", "credit", "currency", "dollars", "finance", "money", "online", "pay", "payment", "price", "quote", "request", "shopping", "symbol" ] +}, { + "name" : "toggle_off", + "tags" : [ "active", "app", "application", "components", "configuration", "control", "design", "disable", "inable", "inactive", "interface", "off", "on", "selection", "settings", "site", "slider", "switch", "toggle", "ui", "ux", "web", "website" ] +}, { + "name" : "book", + "tags" : [ "book", "bookmark", "favorite", "label", "library", "read", "reading", "remember", "ribbon", "save", "tag" ] +}, { + "name" : "contact_page", + "tags" : [ "account", "avatar", "contact", "data", "doc", "document", "drive", "face", "file", "folder", "folders", "human", "page", "people", "person", "profile", "sheet", "slide", "storage", "user", "writing" ] +}, { + "name" : "speed", + "tags" : [ "arrow", "control", "controls", "fast", "gauge", "meter", "motion", "music", "slow", "speed", "speedometer", "velocity", "video" ] +}, { + "name" : "bug_report", + "tags" : [ "animal", "bug", "fix", "insect", "issue", "problem", "report", "testing", "virus", "warning" ] +}, { + "name" : "space_dashboard", + "tags" : [ "cards", "dashboard", "format", "grid", "layout", "rectangle", "shapes", "space", "squares", "web", "website" ] +}, { + "name" : "fiber_manual_record", + "tags" : [ "circle", "dot", "fiber", "manual", "play", "record", "watch" ] +}, { + "name" : "report", + "tags" : [ "!", "alert", "attention", "caution", "danger", "error", "exclamation", "important", "mark", "notification", "octagon", "report", "symbol", "warning" ] +}, { + "name" : "alarm", + "tags" : [ "alarm", "alert", "bell", "clock", "countdown", "date", "notification", "schedule", "time" ] +}, { + "name" : "cached", + "tags" : [ "around", "arrows", "cache", "cached", "inprogress", "load", "loading refresh", "renew", "rotate" ] +}, { + "name" : "translate", + "tags" : [ "language", "speaking", "speech", "translate", "translator", "words" ] +}, { + "name" : "pan_tool", + "tags" : [ "fingers", "gesture", "hand", "hands", "human", "move", "pan", "scan", "stop", "tool" ] +}, { + "name" : "gavel", + "tags" : [ "agreement", "contract", "court", "document", "gavel", "government", "judge", "law", "mallet", "official", "police", "rule", "rules", "terms" ] +}, { + "name" : "settings_suggest", + "tags" : [ "ai", "artificial", "automatic", "automation", "change", "custom", "details", "gear", "genai", "intelligence", "magic", "options", "recommendation", "service", "settings", "smart", "spark", "sparkle", "star", "suggest", "suggestion", "system" ] +}, { + "name" : "file_copy", + "tags" : [ "content", "copy", "cut", "doc", "document", "duplicate", "file", "multiple", "past" ] +}, { + "name" : "edit_calendar", + "tags" : [ "calendar", "compose", "create", "date", "day", "draft", "edit", "editing", "event", "month", "pen", "pencil", "schedule", "write", "writing" ] +}, { + "name" : "contact_mail", + "tags" : [ "account", "address", "avatar", "communicate", "contact", "email", "face", "human", "info", "information", "mail", "message", "people", "person", "profile", "user" ] +}, { + "name" : "quiz", + "tags" : [ "?", "assistance", "faq", "help", "info", "information", "punctuation", "question mark", "quiz", "support", "symbol", "test" ] +}, { + "name" : "supervised_user_circle", + "tags" : [ "account", "avatar", "circle", "control", "face", "human", "parental", "parents", "people", "person", "profile", "supervised", "supervisor", "user" ] +}, { + "name" : "cloud_download", + "tags" : [ "app", "application", "arrow", "backup", "cloud", "connection", "down", "download", "drive", "files", "folders", "internet", "network", "sky", "storage", "upload" ] +}, { + "name" : "stop", + "tags" : [ "control", "controls", "music", "pause", "play", "square", "stop", "video" ] +}, { + "name" : "person_search", + "tags" : [ "account", "avatar", "face", "find", "glass", "human", "look", "magnify", "magnifying", "people", "person", "profile", "search", "user" ] +}, { + "name" : "location_city", + "tags" : [ "apartments", "architecture", "buildings", "business", "city", "estate", "home", "landscape", "location", "place", "real", "residence", "residential", "shelter", "town", "urban" ] +}, { + "name" : "sentiment_very_satisfied", + "tags" : [ "emotions", "expressions", "face", "feelings", "glad", "happiness", "happy", "like", "mood", "person", "pleased", "satisfied", "sentiment", "smile", "smiling", "survey", "very" ] +}, { + "name" : "ios_share", + "tags" : [ "arrow", "export", "ios", "send", "share", "up" ] +}, { + "name" : "minimize", + "tags" : [ "app", "application", "components", "design", "interface", "line", "minimize", "screen", "shape", "site", "ui", "ux", "web", "website" ] +}, { + "name" : "qr_code", + "tags" : [ "barcode", "camera", "code", "media", "product", "qr", "quick", "response", "smartphone", "url", "urls" ] +}, { + "name" : "sentiment_satisfied_alt", + "tags" : [ "account", "alt", "emoji", "face", "happy", "human", "people", "person", "profile", "satisfied", "sentiment", "smile", "user" ] +}, { + "name" : "local_mall", + "tags" : [ "bag", "bill", "building", "business", "buy", "card", "cart", "cash", "coin", "commerce", "credit", "currency", "dollars", "handbag", "local", "mall", "money", "online", "pay", "payment", "shop", "shopping", "store", "storefront" ] +}, { + "name" : "qr_code_2", + "tags" : [ "barcode", "camera", "code", "media", "product", "qr", "quick", "response", "smartphone", "url", "urls" ] +}, { + "name" : "flight", + "tags" : [ "air", "airplane", "airport", "flight", "plane", "transportation", "travel", "trip" ] +}, { + "name" : "desktop_windows", + "tags" : [ "Android", "OS", "chrome", "desktop", "device", "display", "hardware", "iOS", "mac", "monitor", "screen", "television", "tv", "web", "window", "windows" ] +}, { + "name" : "music_note", + "tags" : [ "audio", "audiotrack", "key", "music", "note", "sound", "track" ] +}, { + "name" : "sentiment_satisfied", + "tags" : [ "emotions", "expressions", "face", "feelings", "glad", "happiness", "happy", "like", "mood", "person", "pleased", "satisfied", "sentiment", "smile", "smiling", "survey" ] +}, { + "name" : "android", + "tags" : [ "android", "character", "logo", "mascot", "toy" ] +}, { + "name" : "accessibility", + "tags" : [ "accessibility", "accessible", "body", "handicap", "help", "human", "people", "person" ] +}, { + "name" : "backspace", + "tags" : [ "arrow", "back", "backspace", "cancel", "clear", "correct", "delete", "erase", "remove" ] +}, { + "name" : "precision_manufacturing", + "tags" : [ "arm", "automatic", "chain", "conveyor", "crane", "factory", "industry", "machinery", "manufacturing", "mechanical", "precision", "production", "repairing", "robot", "supply", "warehouse" ] +}, { + "name" : "drag_handle", + "tags" : [ "app", "application ui", "components", "design", "drag", "handle", "interface", "layout", "menu", "move", "screen", "site", "ui", "ux", "web", "website", "window" ] +}, { + "name" : "smart_display", + "tags" : [ "airplay", "cast", "chrome", "connect", "device", "display", "play", "screen", "screencast", "smart", "stream", "television", "tv", "video", "wireless" ] +}, { + "name" : "near_me", + "tags" : [ "destination", "direction", "location", "maps", "me", "navigation", "near", "pin", "place", "point", "stop" ] +}, { + "name" : "west", + "tags" : [ "arrow", "directional", "left", "maps", "navigation", "west" ] +}, { + "name" : "get_app", + "tags" : [ "app", "arrow", "arrows", "down", "download", "downloads", "export", "get", "install", "play", "upload" ] +}, { + "name" : "person_add_alt", + "tags" : [ "+", "account", "add", "face", "human", "people", "person", "plus", "profile", "user" ] +}, { + "name" : "fitness_center", + "tags" : [ "athlete", "center", "dumbbell", "exercise", "fitness", "gym", "hobby", "places", "sport", "weights", "workout" ] +}, { + "name" : "shield", + "tags" : [ "certified", "privacy", "private", "protect", "protection", "security", "shield", "verified" ] +}, { + "name" : "message", + "tags" : [ "bubble", "chat", "comment", "communicate", "feedback", "message", "speech" ] +}, { + "name" : "rocket_launch", + "tags" : [ "launch", "rocket", "space", "spaceship", "takeoff" ] +}, { + "name" : "record_voice_over", + "tags" : [ "account", "face", "human", "over", "people", "person", "profile", "record", "recording", "speak", "speaking", "speech", "transcript", "user", "voice" ] +}, { + "name" : "add_task", + "tags" : [ "+", "add", "approve", "check", "circle", "completed", "increase", "mark", "ok", "plus", "select", "task", "tick", "yes" ] +}, { + "name" : "drive_file_rename_outline", + "tags" : [ "compose", "create", "draft", "drive", "edit", "editing", "file", "input", "marker", "pen", "pencil", "rename", "write", "writing" ] +}, { + "name" : "insert_drive_file", + "tags" : [ "doc", "drive", "file", "format", "insert", "sheet", "slide" ] +}, { + "name" : "question_mark", + "tags" : [ "?", "assistance", "help", "info", "information", "punctuation", "question mark", "support", "symbol" ] +}, { + "name" : "trending_flat", + "tags" : [ "arrow", "change", "data", "flat", "metric", "movement", "rate", "right", "track", "tracking", "trending" ] +}, { + "name" : "handyman", + "tags" : [ "build", "construction", "fix", "hammer", "handyman", "repair", "screw", "screwdriver", "tools" ] +}, { + "name" : "emoji_objects", + "tags" : [ "bulb", "creative", "emoji", "idea", "light", "objects", "solution", "thinking" ] +}, { + "name" : "military_tech", + "tags" : [ "army", "award", "badge", "honor", "medal", "merit", "military", "order", "privilege", "prize", "rank", "reward", "ribbon", "soldier", "star", "status", "tech", "trophy", "win", "winner" ] +}, { + "name" : "hourglass_empty", + "tags" : [ "countdown", "empty", "hourglass", "loading", "minutes", "time", "wait", "waiting" ] +}, { + "name" : "help_center", + "tags" : [ "?", "assistance", "center", "help", "info", "information", "punctuation", "question mark", "recent", "restore", "support", "symbol" ] +}, { + "name" : "science", + "tags" : [ "beaker", "chemical", "chemistry", "experiment", "flask", "glass", "laboratory", "research", "science", "tube" ] +}, { + "name" : "storage", + "tags" : [ "computer", "data", "drive", "memory", "storage" ] +}, { + "name" : "movie", + "tags" : [ "cinema", "film", "media", "movie", "slate", "video" ] +}, { + "name" : "accessibility_new", + "tags" : [ "accessibility", "accessible", "body", "handicap", "help", "human", "new", "people", "person" ] +}, { + "name" : "workspace_premium", + "tags" : [ "certification", "degree", "ecommerce", "guarantee", "medal", "permit", "premium", "ribbon", "verification", "workspace" ] +}, { + "name" : "directions_run", + "tags" : [ "body", "directions", "human", "jogging", "maps", "people", "person", "route", "run", "running", "walk" ] +}, { + "name" : "rule", + "tags" : [ "approve", "check", "complete", "done", "incomplete", "line", "mark", "missing", "no", "ok", "rule", "select", "tick", "validate", "verified", "wrong", "x", "yes" ] +}, { + "name" : "thumb_down", + "tags" : [ "ate", "dislike", "down", "favorite", "fingers", "gesture", "hand", "hands", "like", "rank", "ranking", "rating", "thumb" ] +}, { + "name" : "event_note", + "tags" : [ "calendar", "date", "event", "note", "schedule", "text", "time", "writing" ] +}, { + "name" : "contacts", + "tags" : [ "account", "avatar", "call", "cell", "contacts", "face", "human", "info", "information", "mobile", "people", "person", "phone", "profile", "user" ] +}, { + "name" : "comment", + "tags" : [ "bubble", "chat", "comment", "communicate", "feedback", "message", "outline", "speech" ] +}, { + "name" : "restaurant_menu", + "tags" : [ "book", "dining", "eat", "food", "fork", "knife", "local", "meal", "menu", "restaurant", "spoon" ] +}, { + "name" : "add_photo_alternate", + "tags" : [ "+", "add", "alternate", "image", "landscape", "mountain", "mountains", "new", "photo", "photography", "picture", "plus", "symbol" ] +}, { + "name" : "confirmation_number", + "tags" : [ "admission", "confirmation", "entertainment", "event", "number", "ticket" ] +}, { + "name" : "sticky_note_2", + "tags" : [ "2", "bookmark", "mark", "message", "note", "paper", "sticky", "text", "writing" ] +}, { + "name" : "format_quote", + "tags" : [ "doc", "edit", "editing", "editor", "format", "quotation", "quote", "sheet", "spreadsheet", "text", "type", "writing" ] +}, { + "name" : "history_edu", + "tags" : [ "document", "edu", "education", "feather", "history", "letter", "paper", "pen", "quill", "school", "story", "tools", "write", "writing" ] +}, { + "name" : "business_center", + "tags" : [ "bag", "baggage", "briefcase", "business", "case", "center", "places", "purse", "suitcase", "work" ] +}, { + "name" : "upload", + "tags" : [ "arrow", "arrows", "download", "drive", "up", "upload" ] +}, { + "name" : "skip_previous", + "tags" : [ "arrow", "control", "controls", "music", "next", "play", "previous", "skip", "video" ] +}, { + "name" : "archive", + "tags" : [ "archive", "inbox", "mail", "store" ] +}, { + "name" : "wb_sunny", + "tags" : [ "balance", "bright", "light", "lighting", "sun", "sunny", "wb", "white" ] +}, { + "name" : "cake", + "tags" : [ "add", "baked", "birthday", "cake", "candles", "celebration", "dessert", "food", "frosting", "new", "party", "pastries", "pastry", "plus", "social", "sweet", "symbol" ] +}, { + "name" : "attachment", + "tags" : [ "attach", "attachment", "clip", "compose", "file", "image", "link" ] +}, { + "name" : "source", + "tags" : [ "code", "composer", "content", "creation", "data", "doc", "document", "file", "folder", "mode", "source", "storage", "view" ] +}, { + "name" : "settings_applications", + "tags" : [ "application", "change", "details", "gear", "info", "information", "options", "personal", "service", "settings" ] +}, { + "name" : "dashboard_customize", + "tags" : [ "cards", "customize", "dashboard", "format", "layout", "rectangle", "shapes", "square", "web", "website" ] +}, { + "name" : "find_in_page", + "tags" : [ "data", "doc", "document", "drive", "file", "find", "folder", "folders", "glass", "in", "look", "magnify", "magnifying", "page", "paper", "search", "see", "sheet", "slide", "writing" ] +}, { + "name" : "support", + "tags" : [ "assist", "buoy", "help", "life", "lifebuoy", "rescue", "safe", "safety", "support" ] +}, { + "name" : "ads_click", + "tags" : [ "ads", "browser", "click", "clicks", "cursor", "internet", "target", "traffic", "web" ] +}, { + "name" : "new_releases", + "tags" : [ "approve", "award", "check", "checkmark", "complete", "done", "new", "notification", "ok", "release", "releases", "select", "star", "symbol", "tick", "verification", "verified", "warning", "yes" ] +}, { + "name" : "flutter_dash", + "tags" : [ "bird", "dash", "flutter", "mascot" ] +}, { + "name" : "playlist_add", + "tags" : [ "+", "add", "collection", "list", "music", "new", "playlist", "plus", "symbol" ] +}, { + "name" : "save_alt", + "tags" : [ "alt", "arrow", "disk", "document", "down", "file", "floppy", "multimedia", "save" ] +}, { + "name" : "close_fullscreen", + "tags" : [ "action", "arrow", "arrows", "close", "collapse", "direction", "full", "fullscreen", "minimize", "screen" ] +}, { + "name" : "credit_score", + "tags" : [ "approve", "bill", "card", "cash", "check", "coin", "commerce", "complete", "cost", "credit", "currency", "dollars", "done", "finance", "loan", "mark", "money", "ok", "online", "pay", "payment", "score", "select", "symbol", "tick", "validate", "verified", "yes" ] +}, { + "name" : "layers", + "tags" : [ "arrange", "disabled", "enabled", "interaction", "layers", "maps", "off", "on", "overlay", "pages", "slash" ] +}, { + "name" : "redeem", + "tags" : [ "bill", "card", "cart", "cash", "certificate", "coin", "commerce", "credit", "currency", "dollars", "gift", "giftcard", "money", "online", "pay", "payment", "present", "redeem", "shopping" ] +}, { + "name" : "spa", + "tags" : [ "aromatherapy", "flower", "healthcare", "leaf", "massage", "meditation", "nature", "petals", "places", "relax", "spa", "wellbeing", "wellness" ] +}, { + "name" : "announcement", + "tags" : [ "!", "alert", "announcement", "attention", "bubble", "caution", "chat", "comment", "communicate", "danger", "error", "exclamation", "feedback", "important", "mark", "message", "notification", "speech", "symbol", "warning" ] +}, { + "name" : "keyboard_backspace", + "tags" : [ "arrow", "back", "backspace", "keyboard", "left" ] +}, { + "name" : "loyalty", + "tags" : [ "benefits", "card", "credit", "heart", "loyalty", "membership", "miles", "points", "program", "subscription", "tag", "travel", "trip" ] +}, { + "name" : "swap_vert", + "tags" : [ "arrow", "arrows", "direction", "down", "navigation", "swap", "up", "vert", "vertical" ] +}, { + "name" : "sentiment_dissatisfied", + "tags" : [ "angry", "disappointed", "dislike", "dissatisfied", "emotions", "expressions", "face", "feelings", "frown", "mood", "person", "sad", "sentiment", "survey", "unhappy", "unsatisfied", "upset" ] +}, { + "name" : "medical_services", + "tags" : [ "aid", "bag", "briefcase", "emergency", "first", "kit", "medical", "medicine", "services" ] +}, { + "name" : "view_headline", + "tags" : [ "design", "format", "grid", "headline", "layout", "paragraph", "text", "view", "website" ] +}, { + "name" : "arrow_circle_right", + "tags" : [ "arrow", "circle", "direction", "navigation", "right" ] +}, { + "name" : "format_list_numbered", + "tags" : [ "align", "alignment", "digit", "doc", "edit", "editing", "editor", "format", "list", "notes", "number", "numbered", "sheet", "spreadsheet", "symbol", "text", "type", "writing" ] +}, { + "name" : "phone_android", + "tags" : [ "OS", "android", "cell", "device", "hardware", "iOS", "mobile", "phone", "tablet" ] +}, { + "name" : "sms", + "tags" : [ "3", "bubble", "chat", "communication", "conversation", "dots", "message", "more", "service", "sms", "speech", "three" ] +}, { + "name" : "restore", + "tags" : [ "arrow", "back", "backwards", "clock", "date", "history", "refresh", "renew", "restore", "reverse", "rotate", "schedule", "time", "turn" ] +}, { + "name" : "policy", + "tags" : [ "certified", "find", "glass", "legal", "look", "magnify", "magnifying", "policy", "privacy", "private", "protect", "protection", "search", "security", "see", "shield", "verified" ] +}, { + "name" : "dangerous", + "tags" : [ "broken", "danger", "dangerous", "fix", "no", "sign", "stop", "update", "warning", "wrong", "x" ] +}, { + "name" : "battery_full", + "tags" : [ "battery", "cell", "charge", "full", "mobile", "power" ] +}, { + "name" : "euro_symbol", + "tags" : [ "bill", "card", "cash", "coin", "commerce", "cost", "credit", "currency", "dollars", "euro", "finance", "money", "online", "pay", "payment", "symbol" ] +}, { + "name" : "query_stats", + "tags" : [ "analytics", "chart", "data", "diagram", "find", "glass", "graph", "infographic", "line", "look", "magnify", "magnifying", "measure", "metrics", "query", "search", "see", "statistics", "stats", "tracking" ] +}, { + "name" : "group_work", + "tags" : [ "alliance", "collaboration", "group", "partnership", "team", "teamwork", "together", "work" ] +}, { + "name" : "expand_circle_down", + "tags" : [ "arrow", "arrows", "chevron", "circle", "collapse", "direction", "down", "expand", "expandable", "list", "more" ] +}, { + "name" : "sensors", + "tags" : [ "connection", "network", "scan", "sensors", "signal", "wireless" ] +}, { + "name" : "keyboard_arrow_up", + "tags" : [ "arrow", "arrows", "keyboard", "up" ] +}, { + "name" : "brush", + "tags" : [ "art", "brush", "design", "draw", "edit", "editing", "paint", "painting", "tool" ] +}, { + "name" : "meeting_room", + "tags" : [ "building", "door", "doorway", "entrance", "home", "house", "interior", "meeting", "office", "open", "places", "room" ] +}, { + "name" : "key", + "tags" : [ "key", "lock", "password", "unlock" ] +}, { + "name" : "house", + "tags" : [ "architecture", "building", "estate", "family", "home", "homepage", "house", "place", "places", "real", "residence", "residential", "shelter" ] +}, { + "name" : "lunch_dining", + "tags" : [ "breakfast", "dining", "dinner", "drink", "fastfood", "food", "hamburger", "lunch", "meal" ] +}, { + "name" : "table_chart", + "tags" : [ "analytics", "bar", "bars", "chart", "data", "diagram", "graph", "infographic grid", "measure", "metrics", "statistics", "table", "tracking" ] +}, { + "name" : "border_color", + "tags" : [ "all", "border", "doc", "edit", "editing", "editor", "pen", "pencil", "sheet", "spreadsheet", "stroke", "text", "type", "writing" ] +}, { + "name" : "compare_arrows", + "tags" : [ "arrow", "arrows", "collide", "compare", "direction", "left", "pressure", "push", "right", "together" ] +}, { + "name" : "south", + "tags" : [ "arrow", "directional", "down", "maps", "navigation", "south" ] +}, { + "name" : "directions_walk", + "tags" : [ "body", "direction", "directions", "human", "jogging", "maps", "people", "person", "route", "run", "walk" ] +}, { + "name" : "arrow_left", + "tags" : [ "app", "application", "arrow", "components", "direction", "interface", "left", "navigation", "screen", "site", "ui", "ux", "web", "website" ] +}, { + "name" : "tag", + "tags" : [ "hash", "hashtag", "key", "media", "number", "pound", "social", "tag", "trend" ] +}, { + "name" : "change_circle", + "tags" : [ "around", "arrows", "change", "circle", "direction", "navigation", "rotate" ] +}, { + "name" : "subject", + "tags" : [ "alignment", "doc", "document", "email", "full", "justify", "list", "note", "subject", "text", "writing" ] +}, { + "name" : "sentiment_very_dissatisfied", + "tags" : [ "angry", "disappointed", "dislike", "dissatisfied", "emotions", "expressions", "face", "feelings", "mood", "person", "sad", "sentiment", "sorrow", "survey", "unhappy", "unsatisfied", "upset", "very" ] +}, { + "name" : "local_hospital", + "tags" : [ "911", "aid", "cross", "emergency", "first", "hospital", "local", "medicine" ] +}, { + "name" : "table_view", + "tags" : [ "format", "grid", "group", "layout", "multiple", "table", "view" ] +}, { + "name" : "disabled_by_default", + "tags" : [ "box", "by", "cancel", "close", "default", "disabled", "exit", "no", "quit", "remove", "square", "stop", "x" ] +}, { + "name" : "notification_important", + "tags" : [ "!", "active", "alarm", "alert", "attention", "bell", "caution", "chime", "danger", "error", "exclamation", "important", "mark", "notification", "notifications", "notify", "reminder", "ring", "sound", "symbol", "warning" ] +}, { + "name" : "celebration", + "tags" : [ "activity", "birthday", "celebration", "event", "fun", "party" ] +}, { + "name" : "laptop", + "tags" : [ "Android", "OS", "chrome", "computer", "desktop", "device", "hardware", "iOS", "laptop", "mac", "monitor", "web", "windows" ] +}, { + "name" : "loop", + "tags" : [ "around", "arrow", "arrows", "direction", "inprogress", "load", "loading refresh", "loop", "music", "navigation", "renew", "rotate", "turn" ] +}, { + "name" : "nightlight_round", + "tags" : [ "dark", "half", "light", "mode", "moon", "night", "nightlight", "round" ] +}, { + "name" : "privacy_tip", + "tags" : [ "alert", "announcement", "assistance", "certified", "details", "help", "i", "info", "information", "privacy", "private", "protect", "protection", "security", "service", "shield", "support", "tip", "verified" ] +}, { + "name" : "import_contacts", + "tags" : [ "address", "book", "contacts", "import", "info", "information", "open" ] +}, { + "name" : "equalizer", + "tags" : [ "adjustment", "analytics", "chart", "data", "equalizer", "graph", "measure", "metrics", "music", "noise", "sound", "static", "statistics", "tracking", "volume" ] +}, { + "name" : "app_registration", + "tags" : [ "app", "apps", "edit", "pencil", "register", "registration" ] +}, { + "name" : "keyboard_double_arrow_right", + "tags" : [ "arrow", "arrows", "direction", "double", "multiple", "navigation", "right" ] +}, { + "name" : "handshake", + "tags" : [ "agreement", "hand", "hands", "partnership", "shake" ] +}, { + "name" : "corporate_fare", + "tags" : [ "architecture", "building", "business", "corporate", "estate", "fare", "organization", "place", "real", "residence", "residential", "shelter" ] +}, { + "name" : "local_library", + "tags" : [ "book", "community learning", "library", "local", "read" ] +}, { + "name" : "https", + "tags" : [ "https", "lock", "locked", "password", "privacy", "private", "protection", "safety", "secure", "security" ] +}, { + "name" : "euro", + "tags" : [ "bill", "card", "cash", "coin", "commerce", "cost", "credit", "currency", "dollars", "euro", "euros", "finance", "money", "online", "pay", "payment", "price", "shopping", "symbol" ] +}, { + "name" : "coronavirus", + "tags" : [ "19", "bacteria", "coronavirus", "covid", "disease", "germs", "illness", "sick", "social" ] +}, { + "name" : "price_check", + "tags" : [ "approve", "bill", "card", "cash", "check", "coin", "commerce", "complete", "cost", "credit", "currency", "dollars", "done", "finance", "mark", "money", "ok", "online", "pay", "payment", "price", "select", "shopping", "symbol", "tick", "validate", "verified", "yes" ] +}, { + "name" : "live_tv", + "tags" : [ "Android", "OS", "antennas hardware", "chrome", "desktop", "device", "iOS", "live", "mac", "monitor", "movie", "play", "stream", "television", "tv", "web", "window" ] +}, { + "name" : "park", + "tags" : [ "attraction", "fresh", "local", "nature", "outside", "park", "plant", "tree" ] +}, { + "name" : "toc", + "tags" : [ "content", "format", "lines", "list", "order", "reorder", "stacked", "table", "title", "titles", "toc" ] +}, { + "name" : "track_changes", + "tags" : [ "bullseye", "changes", "circle", "evolve", "lines", "movement", "rotate", "shift", "target", "track" ] +}, { + "name" : "arrow_circle_up", + "tags" : [ "arrow", "circle", "direction", "navigation", "up" ] +}, { + "name" : "emoji_people", + "tags" : [ "arm", "body", "emoji", "greeting", "human", "people", "person", "social", "waving" ] +}, { + "name" : "flash_on", + "tags" : [ "bolt", "disabled", "electric", "enabled", "fast", "flash", "lightning", "off", "on", "slash", "thunderbolt" ] +}, { + "name" : "copyright", + "tags" : [ "alphabet", "c", "character", "copyright", "emblem", "font", "legal", "letter", "owner", "symbol", "text" ] +}, { + "name" : "bookmarks", + "tags" : [ "bookmark", "bookmarks", "favorite", "label", "layers", "library", "multiple", "read", "reading", "remember", "ribbon", "save", "stack", "tag" ] +}, { + "name" : "ac_unit", + "tags" : [ "ac", "air", "cold", "conditioner", "flake", "snow", "temperature", "unit", "weather", "winter" ] +}, { + "name" : "contact_phone", + "tags" : [ "account", "avatar", "call", "communicate", "contact", "face", "human", "info", "information", "message", "mobile", "people", "person", "phone", "profile", "user" ] +}, { + "name" : "keyboard_arrow_left", + "tags" : [ "arrow", "arrows", "keyboard", "left" ] +}, { + "name" : "medication", + "tags" : [ "doctor", "drug", "emergency", "hospital", "medication", "medicine", "pharmacy", "pills", "prescription" ] +}, { + "name" : "grading", + "tags" : [ "'favorite'_new'. ' Remove this icon & keep 'star'.", "'star_boarder'", "'star_border_purple500'", "'star_outline'", "'star_purple500'", "'star_rate'", "Same as 'star'" ] +}, { + "name" : "keyboard_return", + "tags" : [ "arrow", "back", "keyboard", "left", "return" ] +}, { + "name" : "api", + "tags" : [ "api", "developer", "development", "enterprise", "software" ] +}, { + "name" : "smart_toy", + "tags" : [ "bot", "droid", "games", "robot", "smart", "toy" ] +}, { + "name" : "input", + "tags" : [ "arrow", "box", "download", "input", "login", "move", "right" ] +}, { + "name" : "self_improvement", + "tags" : [ "body", "calm", "care", "chi", "human", "improvement", "meditate", "meditation", "people", "person", "relax", "self", "sitting", "wellbeing", "yoga", "zen" ] +}, { + "name" : "live_help", + "tags" : [ "?", "assistance", "bubble", "chat", "comment", "communicate", "help", "info", "information", "live", "message", "punctuation", "question mark", "recent", "restore", "speech", "support", "symbol" ] +}, { + "name" : "query_builder", + "tags" : [ "builder", "clock", "date", "query", "schedule", "time" ] +}, { + "name" : "perm_media", + "tags" : [ "collection", "data", "doc", "document", "file", "folder", "folders", "image", "landscape", "media", "mountain", "mountains", "perm", "photo", "photography", "picture", "storage" ] +}, { + "name" : "download_for_offline", + "tags" : [ "arrow", "circle", "down", "download", "for offline", "install", "upload" ] +}, { + "name" : "view_module", + "tags" : [ "design", "format", "grid", "layout", "module", "square", "squares", "stacked", "view", "website" ] +}, { + "name" : "pin", + "tags" : [ "1", "2", "3", "digit", "key", "login", "logout", "number", "password", "pattern", "pin", "security", "star", "symbol", "unlock" ] +}, { + "name" : "fast_forward", + "tags" : [ "control", "fast", "forward", "media", "music", "play", "speed", "time", "tv", "video" ] +}, { + "name" : "forward_to_inbox", + "tags" : [ "arrow", "arrows", "directions", "email", "envelop", "forward", "inbox", "letter", "mail", "message", "navigation", "outgoing", "right", "send", "to" ] +}, { + "name" : "person_remove", + "tags" : [ "account", "avatar", "delete", "face", "human", "minus", "people", "person", "profile", "remove", "unfriend", "user" ] +}, { + "name" : "local_atm", + "tags" : [ "atm", "bill", "card", "cart", "cash", "coin", "commerce", "credit", "currency", "dollars", "local", "money", "online", "pay", "payment", "shopping", "symbol" ] +}, { + "name" : "star_half", + "tags" : [ "achievement", "bookmark", "favorite", "half", "highlight", "important", "marked", "ranking", "rate", "rating rank", "reward", "save", "saved", "shape", "special", "star", "toggle" ] +}, { + "name" : "build_circle", + "tags" : [ "adjust", "build", "circle", "fix", "repair", "tool", "wrench" ] +}, { + "name" : "redo", + "tags" : [ "arrow", "backward", "forward", "next", "redo", "repeat", "rotate", "undo" ] +}, { + "name" : "web", + "tags" : [ "browser", "internet", "page", "screen", "site", "web", "website", "www" ] +}, { + "name" : "north_east", + "tags" : [ "arrow", "east", "maps", "navigation", "noth", "right", "up" ] +}, { + "name" : "north", + "tags" : [ "arrow", "directional", "maps", "navigation", "north", "up" ] +}, { + "name" : "cottage", + "tags" : [ "architecture", "beach", "cottage", "estate", "home", "house", "lake", "lodge", "maps", "place", "real", "residence", "residential", "stay", "traveling" ] +}, { + "name" : "local_activity", + "tags" : [ "activity", "event", "event ticket", "local", "star", "things", "ticket" ] +}, { + "name" : "currency_exchange", + "tags" : [ "360", "around", "arrow", "arrows", "cash", "coin", "commerce", "currency", "direction", "dollars", "exchange", "inprogress", "money", "pay", "renew", "rotate", "sync", "turn", "universal" ] +}, { + "name" : "video_library", + "tags" : [ "arrow", "collection", "library", "play", "video" ] +}, { + "name" : "hourglass_bottom", + "tags" : [ "bottom", "countdown", "half", "hourglass", "loading", "minute", "minutes", "time", "wait", "waiting" ] +}, { + "name" : "headphones", + "tags" : [ "accessory", "audio", "device", "ear", "earphone", "headphones", "headset", "listen", "music", "sound" ] +}, { + "name" : "zoom_out", + "tags" : [ "find", "glass", "look", "magnify", "magnifying", "minus", "negative", "out", "scale", "search", "see", "size", "small", "smaller", "zoom" ] +}, { + "name" : "poll", + "tags" : [ "analytics", "bar", "bars", "chart", "data", "diagram", "graph", "infographic", "measure", "metrics", "poll", "statistics", "survey", "tracking", "vote" ] +}, { + "name" : "perm_contact_calendar", + "tags" : [ "account", "calendar", "contact", "date", "face", "human", "information", "people", "perm", "person", "profile", "schedule", "time", "user" ] +}, { + "name" : "forward", + "tags" : [ "arrow", "forward", "mail", "message", "playback", "right", "sent" ] +}, { + "name" : "person_pin", + "tags" : [ "account", "avatar", "destination", "direction", "face", "human", "location", "maps", "people", "person", "pin", "place", "profile", "stop", "user" ] +}, { + "name" : "home_work", + "tags" : [ "architecture", "building", "estate", "home", "place", "real", "residence", "residential", "shelter", "work" ] +}, { + "name" : "playlist_add_check", + "tags" : [ "add", "approve", "check", "collection", "complete", "done", "list", "mark", "music", "ok", "playlist", "select", "tick", "validate", "verified", "yes" ] +}, { + "name" : "local_cafe", + "tags" : [ "bottle", "cafe", "coffee", "cup", "drink", "food", "restaurant", "tea" ] +}, { + "name" : "ondemand_video", + "tags" : [ "Android", "OS", "chrome", "demand", "desktop", "device", "hardware", "iOS", "mac", "monitor", "ondemand", "play", "television", "tv", "video", "web", "window" ] +}, { + "name" : "design_services", + "tags" : [ "compose", "create", "design", "draft", "edit", "editing", "input", "pen", "pencil", "ruler", "service", "write", "writing" ] +}, { + "name" : "looks_one", + "tags" : [ "1", "digit", "looks", "numbers", "square", "symbol" ] +}, { + "name" : "backup", + "tags" : [ "arrow", "backup", "cloud", "data", "drive", "files folders", "storage", "up", "upload" ] +}, { + "name" : "newspaper", + "tags" : [ "article", "data", "doc", "document", "drive", "file", "folder", "folders", "magazine", "media", "news", "newspaper", "notes", "page", "paper", "sheet", "slide", "text", "writing" ] +}, { + "name" : "memory", + "tags" : [ "card", "chip", "digital", "memory", "micro", "processor", "sd", "storage" ] +}, { + "name" : "open_with", + "tags" : [ "arrow", "arrows", "direction", "expand", "move", "open", "pan", "with" ] +}, { + "name" : "content_cut", + "tags" : [ "content", "copy", "cut", "doc", "document", "file", "past", "scissors", "trim" ] +}, { + "name" : "keyboard", + "tags" : [ "computer", "device", "hardware", "input", "keyboard", "keypad", "letter", "office", "text", "type" ] +}, { + "name" : "hourglass_top", + "tags" : [ "countdown", "half", "hourglass", "loading", "minute", "minutes", "time", "top", "wait", "waiting" ] +}, { + "name" : "settings_phone", + "tags" : [ "call", "cell", "contact", "device", "hardware", "mobile", "phone", "settings", "telephone" ] +}, { + "name" : "rss_feed", + "tags" : [ "application", "blog", "connection", "data", "feed", "internet", "network", "rss", "service", "signal", "website", "wifi", "wireless" ] +}, { + "name" : "first_page", + "tags" : [ "arrow", "back", "chevron", "first", "left", "page", "rewind" ] +}, { + "name" : "delivery_dining", + "tags" : [ "delivery", "dining", "food", "meal", "restaurant", "scooter", "takeout", "transportation", "vehicle", "vespa" ] +}, { + "name" : "rate_review", + "tags" : [ "comment", "feedback", "pen", "pencil", "rate", "review", "stars", "write" ] +}, { + "name" : "control_point", + "tags" : [ "+", "add", "circle", "control", "plus", "point" ] +}, { + "name" : "gpp_good", + "tags" : [ "certified", "check", "good", "gpp", "ok", "pass", "security", "shield", "sim", "tick" ] +}, { + "name" : "circle_notifications", + "tags" : [ "active", "alarm", "alert", "bell", "chime", "circle", "notifications", "notify", "reminder", "ring", "sound" ] +}, { + "name" : "auto_fix_high", + "tags" : [ "adjust", "ai", "artificial", "auto", "automatic", "automation", "custom", "edit", "editing", "enhance", "erase", "fix", "genai", "high", "intelligence", "magic", "modify", "pen", "smart", "spark", "sparkle", "star", "tool", "wand" ] +}, { + "name" : "book_online", + "tags" : [ "Android", "OS", "admission", "appointment", "book", "cell", "device", "event", "hardware", "iOS", "mobile", "online", "pass", "phone", "reservation", "tablet", "ticket" ] +}, { + "name" : "notes", + "tags" : [ "comment", "doc", "document", "note", "notes", "text", "write", "writing" ] +}, { + "name" : "point_of_sale", + "tags" : [ "checkout", "cost", "machine", "merchant", "money", "of", "pay", "payment", "point", "pos", "retail", "sale", "system", "transaction" ] +}, { + "name" : "perm_phone_msg", + "tags" : [ "bubble", "call", "cell", "chat", "comment", "communicate", "contact", "device", "message", "msg", "perm", "phone", "recording", "speech", "telephone", "voice" ] +}, { + "name" : "speaker_notes", + "tags" : [ "bubble", "chat", "comment", "communicate", "format", "list", "message", "notes", "speaker", "speech", "text" ] +}, { + "name" : "fullscreen_exit", + "tags" : [ "adjust", "app", "application", "components", "exit", "full", "fullscreen", "interface", "screen", "site", "size", "ui", "ux", "view", "web", "website" ] +}, { + "name" : "headset_mic", + "tags" : [ "accessory", "audio", "chat", "device", "ear", "earphone", "headphones", "headset", "listen", "mic", "music", "sound", "talk" ] +}, { + "name" : "create_new_folder", + "tags" : [ "+", "add", "create", "data", "doc", "document", "drive", "file", "folder", "new", "plus", "sheet", "slide", "storage", "symbol" ] +}, { + "name" : "wysiwyg", + "tags" : [ "composer", "mode", "screen", "site", "software", "system", "text", "view", "visibility", "web", "website", "window", "wysiwyg" ] +}, { + "name" : "label_important", + "tags" : [ "favorite", "important", "indent", "label", "library", "mail", "remember", "save", "stamp", "sticker", "tag", "wing" ] +}, { + "name" : "card_membership", + "tags" : [ "bill", "bookmark", "card", "cash", "certificate", "coin", "commerce", "cost", "credit", "currency", "dollars", "finance", "loyalty", "membership", "money", "online", "pay", "payment", "shopping", "subscription" ] +}, { + "name" : "style", + "tags" : [ "booklet", "cards", "filters", "options", "style", "tags" ] +}, { + "name" : "arrow_circle_down", + "tags" : [ "arrow", "circle", "direction", "down", "navigation" ] +}, { + "name" : "file_present", + "tags" : [ "clip", "data", "doc", "document", "drive", "file", "folder", "folders", "note", "paper", "present", "reminder", "sheet", "slide", "storage", "writing" ] +}, { + "name" : "directions_bus", + "tags" : [ "automobile", "bus", "car", "cars", "directions", "maps", "public", "transportation", "vehicle" ] +}, { + "name" : "whatshot", + "tags" : [ "arrow", "circle", "direction", "fire", "frames", "hot", "round", "whatshot" ] +}, { + "name" : "sports_soccer", + "tags" : [ "athlete", "athletic", "ball", "entertainment", "exercise", "football", "game", "hobby", "soccer", "social", "sports" ] +}, { + "name" : "indeterminate_check_box", + "tags" : [ "app", "application", "box", "button", "check", "components", "control", "design", "form", "indeterminate", "interface", "screen", "select", "selected", "selection", "site", "square", "toggle", "ui", "undetermined", "ux", "web", "website" ] +}, { + "name" : "outlined_flag", + "tags" : [ "country", "flag", "goal", "mark", "nation", "outlined", "report", "start" ] +}, { + "name" : "price_change", + "tags" : [ "arrows", "bill", "card", "cash", "change", "coin", "commerce", "cost", "credit", "currency", "dollars", "down", "finance", "money", "online", "pay", "payment", "price", "shopping", "symbol", "up" ] +}, { + "name" : "mark_email_read", + "tags" : [ "approve", "check", "complete", "done", "email", "envelop", "letter", "mail", "mark", "message", "note", "ok", "read", "select", "send", "sent", "tick", "yes" ] +}, { + "name" : "library_add", + "tags" : [ "+", "add", "collection", "layers", "library", "multiple", "music", "new", "plus", "stacked", "symbol", "video" ] +}, { + "name" : "pageview", + "tags" : [ "doc", "document", "find", "glass", "magnifying", "page", "paper", "search", "view" ] +}, { + "name" : "tv", + "tags" : [ "device", "display", "monitor", "screen", "screencast", "stream", "television", "tv", "video", "wireless" ] +}, { + "name" : "inbox", + "tags" : [ "archive", "email", "inbox", "incoming", "mail", "message" ] +}, { + "name" : "adjust", + "tags" : [ "adjust", "alter", "center", "circle", "circles", "dot", "fix", "image", "move", "target" ] +}, { + "name" : "3d_rotation", + "tags" : [ "3", "3d", "D", "alphabet", "arrow", "arrows", "av", "camera", "character", "digit", "font", "letter", "number", "rotation", "symbol", "text", "type", "vr" ] +}, { + "name" : "battery_charging_full", + "tags" : [ "battery", "bolt", "cell", "charge", "charging", "full", "lightening", "mobile", "power", "thunderbolt" ] +}, { + "name" : "chair", + "tags" : [ "chair", "comfort", "couch", "decoration", "furniture", "home", "house", "living", "lounging", "loveseat", "room", "seat", "seating", "sofa" ] +}, { + "name" : "directions_bike", + "tags" : [ "bicycle", "bike", "direction", "directions", "human", "maps", "person", "public", "route", "transportation" ] +}, { + "name" : "mic_off", + "tags" : [ "audio", "disabled", "enabled", "hear", "hearing", "mic", "microphone", "noise", "off", "on", "record", "recording", "slash", "sound", "voice" ] +}, { + "name" : "local_police", + "tags" : [ "911", "badge", "law", "local", "officer", "police", "protect", "protection", "security", "shield" ] +}, { + "name" : "fastfood", + "tags" : [ "drink", "fastfood", "food", "hamburger", "maps", "meal", "places" ] +}, { + "name" : "tungsten", + "tags" : [ "electricity", "indoor", "lamp", "light", "lightbulb", "setting", "tungsten" ] +}, { + "name" : "mood", + "tags" : [ "emoji", "emotions", "expressions", "face", "feelings", "glad", "happiness", "happy", "like", "mood", "person", "pleased", "smile", "smiling", "social", "survey" ] +}, { + "name" : "pause_circle", + "tags" : [ "circle", "control", "controls", "media", "music", "pause", "video" ] +}, { + "name" : "upgrade", + "tags" : [ "arrow", "export", "instal", "line", "replace", "up", "update", "upgrade" ] +}, { + "name" : "recommend", + "tags" : [ "approved", "circle", "confirm", "favorite", "gesture", "hand", "like", "reaction", "recommend", "social", "support", "thumbs", "up", "well" ] +}, { + "name" : "directions_car_filled", + "tags" : [ "automobile", "car", "cars", "direction", "directions", "filled", "maps", "public", "transportation", "vehicle" ] +}, { + "name" : "fmd_good", + "tags" : [ "destination", "direction", "fmd", "good", "location", "maps", "pin", "place", "stop" ] +}, { + "name" : "integration_instructions", + "tags" : [ "brackets", "clipboard", "code", "css", "develop", "developer", "doc", "document", "engineer", "engineering clipboard", "html", "instructions", "integration", "platform" ] +}, { + "name" : "format_bold", + "tags" : [ "B", "alphabet", "bold", "character", "doc", "edit", "editing", "editor", "font", "format", "letter", "sheet", "spreadsheet", "styles", "symbol", "text", "type", "writing" ] +}, { + "name" : "people_outline", + "tags" : [ "accounts", "committee", "face", "family", "friends", "humans", "network", "outline", "people", "persons", "profiles", "social", "team", "users" ] +}, { + "name" : "trending_down", + "tags" : [ "analytics", "arrow", "data", "diagram", "down", "graph", "infographic", "measure", "metrics", "movement", "rate", "rating", "statistics", "tracking", "trending" ] +}, { + "name" : "change_history", + "tags" : [ "change", "history", "shape", "triangle" ] +}, { + "name" : "female", + "tags" : [ "female", "gender", "girl", "lady", "social", "symbol", "woman", "women" ] +}, { + "name" : "link_off", + "tags" : [ "attached", "chain", "clip", "connection", "disabled", "enabled", "link", "linked", "links", "multimedia", "off", "on", "slash", "url" ] +}, { + "name" : "text_fields", + "tags" : [ "T", "add", "alphabet", "character", "field", "fields", "font", "input", "letter", "symbol", "text", "type" ] +}, { + "name" : "swipe", + "tags" : [ "arrow", "arrows", "fingers", "gesture", "hand", "hands", "swipe", "touch" ] +}, { + "name" : "reviews", + "tags" : [ "bubble", "chat", "comment", "communicate", "feedback", "message", "rate", "rating", "recommendation", "reviews", "speech" ] +}, { + "name" : "home_repair_service", + "tags" : [ "box", "equipment", "fix", "home", "kit", "mechanic", "repair", "repairing", "service", "tool", "toolbox", "tools", "workshop" ] +}, { + "name" : "subscriptions", + "tags" : [ "enroll", "list", "media", "order", "play", "signup", "subscribe", "subscriptions" ] +}, { + "name" : "video_call", + "tags" : [ "+", "add", "call", "camera", "chat", "conference", "film", "filming", "hardware", "image", "motion", "new", "picture", "plus", "symbol", "video", "videography" ] +}, { + "name" : "zoom_out_map", + "tags" : [ "arrow", "arrows", "destination", "location", "maps", "move", "out", "place", "stop", "zoom" ] +}, { + "name" : "straighten", + "tags" : [ "length", "measure", "measurement", "ruler", "size", "straighten" ] +}, { + "name" : "arrow_drop_down_circle", + "tags" : [ "app", "application", "arrow", "circle", "components", "direction", "down", "drop", "interface", "navigation", "screen", "site", "ui", "ux", "web", "website" ] +}, { + "name" : "bed", + "tags" : [ "bed", "bedroom", "double", "full", "furniture", "home", "hotel", "house", "king", "night", "pillows", "queen", "rest", "room", "size", "sleep" ] +}, { + "name" : "drive_eta", + "tags" : [ "automobile", "car", "cars", "destination", "direction", "drive", "estimate", "eta", "maps", "public", "transportation", "travel", "trip", "vehicle" ] +}, { + "name" : "class", + "tags" : [ "archive", "book", "bookmark", "class", "favorite", "label", "library", "read", "reading", "remember", "ribbon", "save", "tag" ] +}, { + "name" : "drafts", + "tags" : [ "document", "draft", "drafts", "email", "file", "letter", "mail", "message", "read" ] +}, { + "name" : "ballot", + "tags" : [ "ballot", "bullet", "election", "list", "point", "poll", "vote" ] +}, { + "name" : "volume_mute", + "tags" : [ "audio", "control", "music", "mute", "sound", "speaker", "tv", "volume" ] +}, { + "name" : "table_rows", + "tags" : [ "grid", "layout", "lines", "rows", "stacked", "table" ] +}, { + "name" : "accessible", + "tags" : [ "accessibility", "accessible", "body", "handicap", "help", "human", "people", "person", "wheelchair" ] +}, { + "name" : "stop_circle", + "tags" : [ "circle", "control", "controls", "music", "pause", "play", "square", "stop", "video" ] +}, { + "name" : "family_restroom", + "tags" : [ "bathroom", "child", "children", "family", "father", "kids", "mother", "parents", "restroom", "wc" ] +}, { + "name" : "title", + "tags" : [ "T", "alphabet", "character", "font", "header", "letter", "subject", "symbol", "text", "title", "type" ] +}, { + "name" : "biotech", + "tags" : [ "biotech", "chemistry", "laboratory", "microscope", "research", "science", "technology" ] +}, { + "name" : "insert_emoticon", + "tags" : [ "account", "emoji", "emoticon", "face", "happy", "human", "insert", "people", "person", "profile", "sentiment", "smile", "user" ] +}, { + "name" : "g_translate", + "tags" : [ "emblem", "g", "google", "language", "logo", "mark", "speaking", "speech", "translate", "translator", "words" ] +}, { + "name" : "last_page", + "tags" : [ "app", "application", "arrow", "chevron", "components", "end", "forward", "interface", "last", "page", "right", "screen", "site", "ui", "ux", "web", "website" ] +}, { + "name" : "publish", + "tags" : [ "arrow", "cloud", "file", "import", "publish", "up", "upload" ] +}, { + "name" : "repeat", + "tags" : [ "arrow", "arrows", "control", "controls", "media", "music", "repeat", "video" ] +}, { + "name" : "checklist_rtl", + "tags" : [ "align", "alignment", "approve", "check", "checklist", "complete", "doc", "done", "edit", "editing", "editor", "format", "list", "mark", "notes", "ok", "rtl", "select", "sheet", "spreadsheet", "text", "tick", "type", "validate", "verified", "writing", "yes" ] +}, { + "name" : "wifi_off", + "tags" : [ "connection", "data", "disabled", "enabled", "internet", "network", "off", "offline", "on", "scan", "service", "signal", "slash", "wifi", "wireless" ] +}, { + "name" : "settings_accessibility", + "tags" : [ "accessibility", "body", "details", "human", "information", "people", "person", "personal", "preferences", "profile", "settings", "user" ] +}, { + "name" : "percent", + "tags" : [ "math", "number", "percent", "symbol" ] +}, { + "name" : "insert_photo", + "tags" : [ "image", "insert", "landscape", "mountain", "mountains", "photo", "photography", "picture" ] +}, { + "name" : "hotel", + "tags" : [ "body", "hotel", "human", "people", "person", "sleep", "stay", "travel", "trip" ] +}, { + "name" : "cleaning_services", + "tags" : [ "clean", "cleaning", "dust", "services", "sweep" ] +}, { + "name" : "downloading", + "tags" : [ "arrow", "circle", "down", "download", "downloading", "downloads", "install", "pending", "progress", "upload" ] +}, { + "name" : "expand", + "tags" : [ "arrow", "arrows", "compress", "enlarge", "expand", "grow", "move", "push", "together" ] +}, { + "name" : "local_phone", + "tags" : [ "booth", "call", "communication", "phone", "telecommunication" ] +}, { + "name" : "offline_bolt", + "tags" : [ "bolt", "circle", "electric", "fast", "lightning", "offline", "thunderbolt" ] +}, { + "name" : "auto_graph", + "tags" : [ "analytics", "auto", "chart", "data", "diagram", "graph", "infographic", "line", "measure", "metrics", "stars", "statistics", "tracking" ] +}, { + "name" : "local_grocery_store", + "tags" : [ "grocery", "market", "shop", "store" ] +}, { + "name" : "photo_library", + "tags" : [ "album", "image", "library", "mountain", "mountains", "photo", "photography", "picture" ] +}, { + "name" : "miscellaneous_services", + "tags" : [ ] +}, { + "name" : "note_alt", + "tags" : [ "alt", "clipboard", "document", "file", "memo", "note", "page", "paper", "writing" ] +}, { + "name" : "settings_backup_restore", + "tags" : [ "arrow", "back", "backup", "backwards", "refresh", "restore", "reverse", "rotate", "settings" ] +}, { + "name" : "production_quantity_limits", + "tags" : [ "!", "alert", "attention", "bill", "card", "cart", "cash", "caution", "coin", "commerce", "credit", "currency", "danger", "dollars", "error", "exclamation", "important", "limits", "mark", "money", "notification", "online", "pay", "payment", "production", "quantity", "shopping", "symbol", "warning" ] +}, { + "name" : "person_off", + "tags" : [ "account", "avatar", "disabled", "enabled", "face", "human", "off", "on", "people", "person", "profile", "slash", "user" ] +}, { + "name" : "report_gmailerrorred", + "tags" : [ "!", "alert", "attention", "caution", "danger", "error", "exclamation", "gmail", "gmailerrorred", "important", "mark", "notification", "octagon", "report", "symbol", "warning" ] +}, { + "name" : "camera", + "tags" : [ "aperture", "camera", "lens", "photo", "photography", "picture", "shutter" ] +}, { + "name" : "recycling", + "tags" : [ "bio", "eco", "green", "loop", "recyclable", "recycle", "recycling", "rotate", "sustainability", "sustainable", "trash" ] +}, { + "name" : "male", + "tags" : [ "boy", "gender", "male", "man", "social", "symbol" ] +}, { + "name" : "not_interested", + "tags" : [ "cancel", "close", "dislike", "exit", "interested", "no", "not", "off", "quit", "remove", "stop", "x" ] +}, { + "name" : "event_busy", + "tags" : [ "busy", "calendar", "cancel", "close", "date", "event", "exit", "no", "remove", "schedule", "stop", "time", "unavailable", "x" ] +}, { + "name" : "arrow_circle_left", + "tags" : [ "arrow", "circle", "direction", "left", "navigation" ] +}, { + "name" : "shuffle", + "tags" : [ "arrow", "arrows", "control", "controls", "music", "random", "shuffle", "video" ] +}, { + "name" : "aspect_ratio", + "tags" : [ "aspect", "expand", "image", "ratio", "resize", "scale", "size", "square" ] +}, { + "name" : "other_houses", + "tags" : [ "architecture", "cottage", "estate", "home", "house", "houses", "maps", "other", "place", "real", "residence", "residential", "stay", "traveling" ] +}, { + "name" : "model_training", + "tags" : [ "arrow", "bulb", "idea", "inprogress", "light", "load", "loading", "model", "refresh", "renew", "restore", "reverse", "rotate", "training" ] +}, { + "name" : "unfold_less", + "tags" : [ "arrow", "arrows", "chevron", "collapse", "direction", "expand", "expandable", "inward", "less", "list", "navigation", "unfold", "up" ] +}, { + "name" : "insert_chart_outlined", + "tags" : [ "analytics", "bar", "bars", "chart", "data", "diagram", "graph", "infographic", "insert", "measure", "metrics", "outlined", "statistics", "tracking" ] +}, { + "name" : "donut_large", + "tags" : [ "analytics", "chart", "data", "diagram", "donut", "graph", "infographic", "inprogress", "large", "measure", "metrics", "pie", "statistics", "tracking" ] +}, { + "name" : "view_column", + "tags" : [ "column", "design", "format", "grid", "layout", "vertical", "view", "website" ] +}, { + "name" : "segment", + "tags" : [ "alignment", "fonts", "format", "lines", "list", "paragraph", "part", "piece", "rule", "rules", "segment", "style", "text" ] +}, { + "name" : "checkroom", + "tags" : [ "checkroom", "closet", "clothes", "coat check", "hanger" ] +}, { + "name" : "mode", + "tags" : [ "compose", "create", "draft", "draw", "edit", "mode", "pen", "pencil", "write" ] +}, { + "name" : "portrait", + "tags" : [ "account", "face", "human", "people", "person", "photo", "picture", "portrait", "profile", "user" ] +}, { + "name" : "camera_alt", + "tags" : [ "alt", "camera", "image", "photo", "photography", "picture" ] +}, { + "name" : "keyboard_double_arrow_left", + "tags" : [ "arrow", "arrows", "direction", "double", "left", "multiple", "navigation" ] +}, { + "name" : "delete_sweep", + "tags" : [ "bin", "can", "delete", "garbage", "remove", "sweep", "trash" ] +}, { + "name" : "hub", + "tags" : [ "center", "connection", "core", "focal point", "hub", "network", "nucleus", "topology" ] +}, { + "name" : "audiotrack", + "tags" : [ "audio", "audiotrack", "key", "music", "note", "sound", "track" ] +}, { + "name" : "calendar_view_month", + "tags" : [ "calendar", "date", "day", "event", "format", "grid", "layout", "month", "schedule", "today", "view" ] +}, { + "name" : "draw", + "tags" : [ "compose", "create", "design", "draft", "draw", "edit", "editing", "input", "pen", "pencil", "write", "writing" ] +}, { + "name" : "navigation", + "tags" : [ "destination", "direction", "location", "maps", "navigation", "pin", "place", "point", "stop" ] +}, { + "name" : "folder_shared", + "tags" : [ "account", "collaboration", "data", "doc", "document", "drive", "face", "file", "folder", "human", "people", "person", "profile", "share", "shared", "sheet", "slide", "storage", "team", "user" ] +}, { + "name" : "read_more", + "tags" : [ "arrow", "more", "read", "text" ] +}, { + "name" : "stacked_bar_chart", + "tags" : [ "analytics", "bar", "chart-chart", "data", "diagram", "graph", "infographic", "measure", "metrics", "stacked", "statistics", "tracking" ] +}, { + "name" : "mode_comment", + "tags" : [ "bubble", "chat", "comment", "communicate", "feedback", "message", "mode comment", "speech" ] +}, { + "name" : "schedule_send", + "tags" : [ "calendar", "clock", "date", "email", "letter", "mail", "remember", "schedule", "send", "share", "time" ] +}, { + "name" : "bluetooth", + "tags" : [ "bluetooth", "cast", "connect", "connection", "device", "paring", "streaming", "symbol", "wireless" ] +}, { + "name" : "graphic_eq", + "tags" : [ "audio", "eq", "equalizer", "graphic", "music", "recording", "sound", "voice" ] +}, { + "name" : "markunread", + "tags" : [ "email", "envelop", "letter", "mail", "markunread", "message", "send", "unread" ] +}, { + "name" : "alarm_on", + "tags" : [ "alarm", "alert", "bell", "clock", "disabled", "duration", "enabled", "notification", "off", "on", "slash", "time", "timer", "watch" ] +}, { + "name" : "local_gas_station", + "tags" : [ "auto", "car", "gas", "local", "oil", "station", "vehicle" ] +}, { + "name" : "person_add_alt_1", + "tags" : [ ] +}, { + "name" : "maximize", + "tags" : [ "app", "application", "components", "design", "interface", "line", "maximize", "screen", "shape", "site", "ui", "ux", "web", "website" ] +}, { + "name" : "bookmark_add", + "tags" : [ "+", "add", "bookmark", "favorite", "plus", "remember", "ribbon", "save", "symbol" ] +}, { + "name" : "dvr", + "tags" : [ "Android", "OS", "audio", "chrome", "computer", "desktop", "device", "display", "dvr", "electronic", "hardware", "iOS", "list", "mac", "monitor", "record", "recorder", "screen", "tv", "video", "web", "window" ] +}, { + "name" : "do_not_disturb_on", + "tags" : [ "cancel", "close", "denied", "deny", "disabled", "disturb", "do", "enabled", "off", "on", "remove", "silence", "slash", "stop" ] +}, { + "name" : "train", + "tags" : [ "automobile", "car", "cars", "direction", "maps", "public", "rail", "subway", "train", "transportation", "vehicle" ] +}, { + "name" : "person_pin_circle", + "tags" : [ "account", "circle", "destination", "direction", "face", "human", "location", "maps", "people", "person", "pin", "place", "profile", "stop", "user" ] +}, { + "name" : "square_foot", + "tags" : [ "construction", "feet", "foot", "inches", "length", "measurement", "ruler", "school", "set", "square", "tools" ] +}, { + "name" : "more_time", + "tags" : [ "+", "add", "clock", "date", "more", "new", "plus", "schedule", "symbol", "time" ] +}, { + "name" : "document_scanner", + "tags" : [ "article", "data", "doc", "document", "drive", "file", "folder", "folders", "notes", "page", "paper", "scan", "scanner", "sheet", "slide", "text", "writing" ] +}, { + "name" : "thumbs_up_down", + "tags" : [ "dislike", "down", "favorite", "fingers", "gesture", "hands", "like", "rate", "rating", "thumbs", "up" ] +}, { + "name" : "settings_ethernet", + "tags" : [ "arrows", "computer", "connect", "connection", "connectivity", "dots", "ethernet", "internet", "network", "settings", "wifi" ] +}, { + "name" : "sort_by_alpha", + "tags" : [ "alphabet", "alphabetize", "az", "by alpha", "character", "font", "letter", "list", "order", "organize", "sort", "symbol", "text", "type" ] +}, { + "name" : "theaters", + "tags" : [ "film", "movie", "movies", "show", "showtimes", "theater", "theaters", "watch" ] +}, { + "name" : "cloud_done", + "tags" : [ "app", "application", "approve", "backup", "check", "cloud", "complete", "connection", "done", "drive", "files", "folders", "internet", "mark", "network", "ok", "select", "sky", "storage", "tick", "upload", "validate", "verified", "yes" ] +}, { + "name" : "local_parking", + "tags" : [ "alphabet", "auto", "car", "character", "font", "garage", "letter", "local", "park", "parking", "symbol", "text", "type", "vehicle" ] +}, { + "name" : "view_agenda", + "tags" : [ "agenda", "cards", "design", "format", "grid", "layout", "stacked", "view", "website" ] +}, { + "name" : "mark_email_unread", + "tags" : [ "check", "circle", "email", "envelop", "letter", "mail", "mark", "message", "note", "notification", "send", "unread" ] +}, { + "name" : "local_florist", + "tags" : [ "florist", "flower", "local", "shop" ] +}, { + "name" : "connect_without_contact", + "tags" : [ "communicating", "connect", "contact", "distance", "people", "signal", "social", "socialize", "without" ] +}, { + "name" : "thumb_down_off_alt", + "tags" : [ "disabled", "dislike", "down", "enabled", "favorite", "filled", "fingers", "gesture", "hand", "hands", "like", "off", "offline", "on", "rank", "ranking", "rate", "rating", "slash", "thumb" ] +}, { + "name" : "sentiment_neutral", + "tags" : [ "emotionless", "emotions", "expressions", "face", "feelings", "fine", "indifference", "mood", "neutral", "okay", "person", "sentiment", "survey" ] +}, { + "name" : "call_end", + "tags" : [ "call", "cell", "contact", "device", "end", "hardware", "mobile", "phone", "telephone" ] +}, { + "name" : "subdirectory_arrow_right", + "tags" : [ "arrow", "directory", "down", "navigation", "right", "sub", "subdirectory" ] +}, { + "name" : "diamond", + "tags" : [ "diamond", "fashion", "gems", "jewelry", "logo", "retail", "valuable", "valuables" ] +}, { + "name" : "podcasts", + "tags" : [ "broadcast", "casting", "network", "podcasts", "signal", "transmitting", "wireless" ] +}, { + "name" : "monitor_heart", + "tags" : [ "baseline", "device", "ecc", "ecg", "fitness", "health", "heart", "medical", "monitor", "track" ] +}, { + "name" : "all_inclusive", + "tags" : [ "all", "endless", "forever", "inclusive", "infinity", "loop", "mobius", "neverending", "strip", "sustainability", "sustainable" ] +}, { + "name" : "wc", + "tags" : [ "bathroom", "closet", "female", "male", "man", "restroom", "room", "wash", "water", "wc", "women" ] +}, { + "name" : "grass", + "tags" : [ "backyard", "fodder", "grass", "ground", "home", "lawn", "plant", "turf", "yard" ] +}, { + "name" : "important_devices", + "tags" : [ "Android", "OS", "desktop", "devices", "hardware", "iOS", "important", "mobile", "monitor", "phone", "star", "tablet", "web" ] +}, { + "name" : "back_hand", + "tags" : [ "back", "fingers", "gesture", "hand", "raised" ] +}, { + "name" : "hiking", + "tags" : [ "backpacking", "bag", "climbing", "duffle", "hiking", "mountain", "social", "sports", "stick", "trail", "travel", "walking" ] +}, { + "name" : "masks", + "tags" : [ "air", "cover", "covid", "face", "hospital", "masks", "medical", "pollution", "protection", "respirator", "sick", "social" ] +}, { + "name" : "waving_hand", + "tags" : [ "bye", "fingers", "gesture", "goodbye", "greetings", "hand", "hello", "palm", "wave", "waving" ] +}, { + "name" : "architecture", + "tags" : [ "architecture", "art", "compass", "design", "draw", "drawing", "engineering", "geometric", "tool" ] +}, { + "name" : "local_post_office", + "tags" : [ "delivery", "email", "envelop", "letter", "local", "mail", "message", "office", "package", "parcel", "post", "postal", "send", "stamp" ] +}, { + "name" : "functions", + "tags" : [ "average", "calculate", "count", "custom", "doc", "edit", "editing", "editor", "functions", "math", "sheet", "spreadsheet", "style", "sum", "text", "type", "writing" ] +}, { + "name" : "directions", + "tags" : [ "arrow", "directions", "maps", "right", "route", "sign", "traffic" ] +}, { + "name" : "money", + "tags" : [ "100", "bill", "card", "cash", "coin", "commerce", "cost", "credit", "currency", "digit", "dollars", "finance", "money", "number", "online", "pay", "payment", "price", "shopping", "symbol" ] +}, { + "name" : "unpublished", + "tags" : [ "approve", "check", "circle", "complete", "disabled", "done", "enabled", "mark", "off", "ok", "on", "select", "slash", "tick", "unpublished", "validate", "verified", "yes" ] +}, { + "name" : "notifications_off", + "tags" : [ "active", "alarm", "alert", "bell", "chime", "disabled", "enabled", "notifications", "notify", "off", "offline", "on", "reminder", "ring", "slash", "sound" ] +}, { + "name" : "airport_shuttle", + "tags" : [ "airport", "automobile", "car", "cars", "commercial", "delivery", "direction", "maps", "mini", "public", "shuttle", "transport", "transportation", "travel", "truck", "van", "vehicle" ] +}, { + "name" : "insert_link", + "tags" : [ "add", "attach", "clip", "file", "insert", "link", "mail", "media" ] +}, { + "name" : "thumb_down_alt", + "tags" : [ "bad", "decline", "disapprove", "dislike", "down", "feedback", "hate", "negative", "no", "reject", "social", "thumb", "veto", "vote" ] +}, { + "name" : "two_wheeler", + "tags" : [ "automobile", "bike", "car", "cars", "direction", "maps", "motorcycle", "public", "scooter", "sport", "transportation", "travel", "two wheeler", "vehicle" ] +}, { + "name" : "nightlight", + "tags" : [ "dark", "disturb", "mode", "moon", "night", "nightlight", "sleep" ] +}, { + "name" : "mic_none", + "tags" : [ "hear", "hearing", "mic", "microphone", "noise", "none", "record", "sound", "voice" ] +}, { + "name" : "keyboard_double_arrow_down", + "tags" : [ "arrow", "arrows", "direction", "double", "down", "multiple", "navigation" ] +}, { + "name" : "invert_colors", + "tags" : [ "colors", "drop", "droplet", "edit", "editing", "hue", "invert", "inverted", "palette", "tone", "water" ] +}, { + "name" : "clear_all", + "tags" : [ "all", "clear", "doc", "document", "format", "lines", "list" ] +}, { + "name" : "mouse", + "tags" : [ "click", "computer", "cursor", "device", "hardware", "mouse", "wireless" ] +}, { + "name" : "mode_edit_outline", + "tags" : [ "compose", "create", "draft", "draw", "edit", "mode", "outline", "pen", "pencil", "write" ] +}, { + "name" : "open_in_browser", + "tags" : [ "arrow", "browser", "in", "open", "site", "up", "web", "website", "window" ] +}, { + "name" : "insert_invitation", + "tags" : [ "calendar", "date", "day", "event", "insert", "invitation", "mark", "month", "range", "remember", "reminder", "today", "week" ] +}, { + "name" : "fast_rewind", + "tags" : [ "back", "control", "fast", "media", "music", "play", "rewind", "speed", "time", "tv", "video" ] +}, { + "name" : "opacity", + "tags" : [ "color", "drop", "droplet", "hue", "invert", "inverted", "opacity", "palette", "tone", "water" ] +}, { + "name" : "video_camera_front", + "tags" : [ "account", "camera", "face", "front", "human", "image", "people", "person", "photo", "photography", "picture", "profile", "user", "video" ] +}, { + "name" : "commute", + "tags" : [ "automobile", "car", "commute", "direction", "maps", "public", "train", "transportation", "trip", "vehicle" ] +}, { + "name" : "addchart", + "tags" : [ "+", "addchart", "analytics", "bar", "bars", "chart", "data", "diagram", "graph", "infographic", "measure", "metrics", "new", "plus", "statistics", "symbol", "tracking" ] +}, { + "name" : "no_accounts", + "tags" : [ "account", "accounts", "avatar", "disabled", "enabled", "face", "human", "no", "off", "offline", "on", "people", "person", "profile", "slash", "thumbnail", "unavailable", "unidentifiable", "unknown", "user" ] +}, { + "name" : "coffee", + "tags" : [ "beverage", "coffee", "cup", "drink", "mug", "plate", "set", "tea" ] +}, { + "name" : "luggage", + "tags" : [ "airport", "bag", "baggage", "carry", "flight", "hotel", "luggage", "on", "suitcase", "travel", "trip" ] +}, { + "name" : "workspaces", + "tags" : [ "circles", "collaboration", "dot", "filled", "group", "outline", "space", "team", "work", "workspaces" ] +}, { + "name" : "child_care", + "tags" : [ "babies", "baby", "care", "child", "children", "face", "infant", "kids", "newborn", "toddler", "young" ] +}, { + "name" : "sports_score", + "tags" : [ "destination", "flag", "goal", "score", "sports" ] +}, { + "name" : "library_music", + "tags" : [ "add", "album", "collection", "library", "music", "song", "sounds" ] +}, { + "name" : "history_toggle_off", + "tags" : [ "clock", "date", "history", "off", "schedule", "time", "toggle" ] +}, { + "name" : "system_update_alt", + "tags" : [ "arrow", "down", "download", "export", "system", "update" ] +}, { + "name" : "access_time", + "tags" : [ ] +}, { + "name" : "rotate_right", + "tags" : [ "around", "arrow", "direction", "inprogress", "load", "loading refresh", "renew", "right", "rotate", "turn" ] +}, { + "name" : "color_lens", + "tags" : [ "art", "color", "lens", "paint", "pallet" ] +}, { + "name" : "grid_on", + "tags" : [ "collage", "disabled", "enabled", "grid", "image", "layout", "off", "on", "slash", "view" ] +}, { + "name" : "crop_free", + "tags" : [ "adjust", "adjustments", "crop", "edit", "editing", "focus", "frame", "free", "image", "photo", "photos", "settings", "size", "zoom" ] +}, { + "name" : "cloud_queue", + "tags" : [ "cloud", "connection", "internet", "network", "queue", "sky", "upload" ] +}, { + "name" : "keyboard_voice", + "tags" : [ "keyboard", "mic", "microphone", "noise", "record", "recorder", "speaker", "voice" ] +}, { + "name" : "format_align_left", + "tags" : [ "align", "alignment", "doc", "edit", "editing", "editor", "format", "left", "sheet", "spreadsheet", "text", "type", "writing" ] +}, { + "name" : "view_week", + "tags" : [ "bars", "columns", "design", "format", "grid", "layout", "view", "website", "week" ] +}, { + "name" : "real_estate_agent", + "tags" : [ "agent", "architecture", "broker", "estate", "hand", "home", "house", "loan", "mortgage", "property", "real", "residence", "residential", "sales", "social" ] +}, { + "name" : "horizontal_rule", + "tags" : [ "gmail", "horizontal", "line", "novitas", "rule" ] +}, { + "name" : "topic", + "tags" : [ "data", "doc", "document", "drive", "file", "folder", "sheet", "slide", "storage", "topic" ] +}, { + "name" : "shower", + "tags" : [ "bath", "bathroom", "closet", "home", "house", "place", "plumbing", "room", "shower", "sprinkler", "wash", "water", "wc" ] +}, { + "name" : "format_italic", + "tags" : [ "alphabet", "character", "doc", "edit", "editing", "editor", "font", "format", "italic", "letter", "sheet", "spreadsheet", "style", "symbol", "text", "type", "writing" ] +}, { + "name" : "traffic", + "tags" : [ "direction", "light", "maps", "signal", "street", "traffic" ] +}, { + "name" : "add_business", + "tags" : [ "+", "add", "bill", "building", "business", "card", "cash", "coin", "commerce", "company", "credit", "currency", "dollars", "market", "money", "new", "online", "pay", "payment", "plus", "shop", "shopping", "store", "storefront", "symbol" ] +}, { + "name" : "electrical_services", + "tags" : [ "charge", "cord", "electric", "electrical", "plug", "power", "services", "wire" ] +}, { + "name" : "timelapse", + "tags" : [ "duration", "motion", "photo", "time", "timelapse", "timer", "video" ] +}, { + "name" : "youtube_searched_for", + "tags" : [ "arrow", "back", "backwards", "find", "glass", "history", "inprogress", "load", "loading", "look", "magnify", "magnifying", "refresh", "renew", "restore", "reverse", "rotate", "search", "see", "youtube" ] +}, { + "name" : "front_hand", + "tags" : [ "fingers", "front", "gesture", "hand", "hello", "palm", "stop" ] +}, { + "name" : "yard", + "tags" : [ "backyard", "flower", "garden", "home", "house", "nature", "pettle", "plants", "yard" ] +}, { + "name" : "tour", + "tags" : [ "destination", "flag", "places", "tour", "travel", "visit" ] +}, { + "name" : "factory", + "tags" : [ "factory", "industry", "manufacturing", "warehouse" ] +}, { + "name" : "developer_board", + "tags" : [ "board", "chip", "computer", "developer", "development", "hardware", "microchip", "processor" ] +}, { + "name" : "more", + "tags" : [ "3", "archive", "bookmark", "dots", "etc", "favorite", "indent", "label", "more", "remember", "save", "stamp", "sticker", "tab", "tag", "three" ] +}, { + "name" : "star_purple500", + "tags" : [ "500", "best", "bookmark", "favorite", "highlight", "purple", "ranking", "rate", "rating", "save", "star", "toggle" ] +}, { + "name" : "format_color_fill", + "tags" : [ "bucket", "color", "doc", "edit", "editing", "editor", "fill", "format", "paint", "sheet", "spreadsheet", "style", "text", "type", "writing" ] +}, { + "name" : "beach_access", + "tags" : [ "access", "beach", "places", "summer", "sunny", "umbrella" ] +}, { + "name" : "local_bar", + "tags" : [ "alcohol", "bar", "bottle", "club", "cocktail", "drink", "food", "liquor", "local", "wine" ] +}, { + "name" : "add_link", + "tags" : [ "add", "attach", "clip", "link", "new", "plus", "symbol" ] +}, { + "name" : "landscape", + "tags" : [ "image", "landscape", "mountain", "mountains", "nature", "photo", "photography", "picture" ] +}, { + "name" : "slideshow", + "tags" : [ "movie", "photos", "play", "slideshow", "square", "video", "view" ] +}, { + "name" : "stream", + "tags" : [ "cast", "connected", "feed", "live", "network", "signal", "stream", "wireless" ] +}, { + "name" : "videocam_off", + "tags" : [ "cam", "camera", "conference", "disabled", "enabled", "film", "filming", "hardware", "image", "motion", "off", "offline", "on", "picture", "slash", "video", "videography" ] +}, { + "name" : "directions_boat", + "tags" : [ "automobile", "boat", "car", "cars", "direction", "directions", "ferry", "maps", "public", "transportation", "vehicle" ] +}, { + "name" : "download_done", + "tags" : [ "arrow", "arrows", "check", "done", "down", "download", "downloads", "drive", "install", "installed", "ok", "tick", "upload" ] +}, { + "name" : "volume_down", + "tags" : [ "audio", "control", "down", "music", "sound", "speaker", "tv", "volume" ] +}, { + "name" : "alt_route", + "tags" : [ "alt", "alternate", "alternative", "arrows", "direction", "maps", "navigation", "options", "other", "route", "routes", "split", "symbol" ] +}, { + "name" : "mood_bad", + "tags" : [ "bad", "disappointment", "dislike", "emoji", "emotions", "expressions", "face", "feelings", "mood", "person", "rating", "social", "survey", "unhappiness", "unhappy", "unpleased", "unsmile", "unsmiling" ] +}, { + "name" : "vaccines", + "tags" : [ "aid", "covid", "doctor", "drug", "emergency", "hospital", "immunity", "injection", "medical", "medication", "medicine", "needle", "pharmacy", "sick", "syringe", "vaccination", "vaccines", "vial" ] +}, { + "name" : "dialpad", + "tags" : [ "buttons", "call", "contact", "device", "dial", "dialpad", "dots", "mobile", "numbers", "pad", "phone" ] +}, { + "name" : "route", + "tags" : [ "directions", "maps", "path", "route", "sign", "traffic" ] +}, { + "name" : "hide_source", + "tags" : [ "circle", "disabled", "enabled", "hide", "off", "offline", "on", "shape", "slash", "source" ] +}, { + "name" : "bookmark_added", + "tags" : [ "added", "approve", "bookmark", "check", "complete", "done", "favorite", "mark", "ok", "remember", "save", "select", "tick", "validate", "verified", "yes" ] +}, { + "name" : "mark_as_unread", + "tags" : [ "as", "envelop", "letter", "mail", "mark", "post", "postal", "read", "receive", "send", "unread" ] +}, { + "name" : "plagiarism", + "tags" : [ "doc", "document", "find", "glass", "look", "magnifying", "page", "paper", "plagiarism", "search", "see" ] +}, { + "name" : "turned_in", + "tags" : [ "archive", "bookmark", "favorite", "in", "label", "library", "read", "reading", "remember", "ribbon", "save", "tag", "turned" ] +}, { + "name" : "settings_input_antenna", + "tags" : [ "airplay", "antenna", "arrows", "cast", "computer", "connect", "connection", "connectivity", "dots", "input", "internet", "network", "screencast", "settings", "stream", "wifi", "wireless" ] +}, { + "name" : "shop", + "tags" : [ "bag", "bill", "buy", "card", "cart", "cash", "coin", "commerce", "credit", "currency", "dollars", "google", "money", "online", "pay", "payment", "play", "shop", "shopping", "store" ] +}, { + "name" : "pool", + "tags" : [ "athlete", "athletic", "beach", "body", "entertainment", "exercise", "hobby", "human", "ocean", "people", "person", "places", "pool", "sea", "sports", "swim", "swimming", "water" ] +}, { + "name" : "search_off", + "tags" : [ "cancel", "close", "disabled", "enabled", "find", "glass", "look", "magnify", "magnifying", "off", "on", "search", "see", "slash", "stop", "x" ] +}, { + "name" : "approval", + "tags" : [ "apply", "approval", "approvals", "approve", "certificate", "certification", "disapproval", "drive", "file", "impression", "ink", "mark", "postage", "stamp" ] +}, { + "name" : "currency_rupee", + "tags" : [ "bill", "card", "cash", "coin", "commerce", "cost", "credit", "currency", "dollars", "finance", "money", "online", "pay", "payment", "price", "rupee", "shopping", "symbol" ] +}, { + "name" : "power", + "tags" : [ "charge", "cord", "electric", "electrical", "outlet", "plug", "power" ] +}, { + "name" : "collections_bookmark", + "tags" : [ "album", "archive", "bookmark", "collections", "favorite", "gallery", "label", "library", "read", "reading", "remember", "ribbon", "save", "stack", "tag" ] +}, { + "name" : "not_started", + "tags" : [ "circle", "media", "not", "pause", "play", "started", "video" ] +}, { + "name" : "pedal_bike", + "tags" : [ "automobile", "bicycle", "bike", "car", "cars", "direction", "human", "maps", "pedal", "public", "route", "scooter", "transportation", "vehicle", "vespa" ] +}, { + "name" : "water", + "tags" : [ "aqua", "beach", "lake", "ocean", "river", "water", "waves", "weather" ] +}, { + "name" : "router", + "tags" : [ "box", "cable", "connection", "hardware", "internet", "network", "router", "signal", "wifi" ] +}, { + "name" : "flight_land", + "tags" : [ "airport", "arrival", "arriving", "flight", "fly", "land", "landing", "plane", "transportation", "travel" ] +}, { + "name" : "shopping_cart_checkout", + "tags" : [ "arrow", "cart", "cash", "checkout", "coin", "commerce", "currency", "dollars", "money", "online", "pay", "payment", "right", "shopping" ] +}, { + "name" : "agriculture", + "tags" : [ "agriculture", "automobile", "car", "cars", "cultivation", "farm", "harvest", "maps", "tractor", "transport", "travel", "truck", "vehicle" ] +}, { + "name" : "where_to_vote", + "tags" : [ "approve", "ballot", "check", "complete", "destination", "direction", "done", "location", "maps", "mark", "ok", "pin", "place", "poll", "select", "stop", "tick", "to", "validate election", "verified", "vote", "where", "yes" ] +}, { + "name" : "beenhere", + "tags" : [ "approve", "archive", "beenhere", "bookmark", "check", "complete", "done", "favorite", "label", "library", "mark", "ok", "read", "reading", "remember", "ribbon", "save", "select", "tag", "tick", "validate", "verified", "yes" ] +}, { + "name" : "add_comment", + "tags" : [ "+", "add", "bubble", "chat", "comment", "communicate", "feedback", "message", "new", "plus", "speech", "symbol" ] +}, { + "name" : "copy_all", + "tags" : [ "all", "content", "copy", "cut", "doc", "document", "file", "multiple", "page", "paper", "past" ] +}, { + "name" : "dynamic_feed", + "tags" : [ "'mail_outline'", "'markunread'. Keep 'mail' and remove others.", "Duplicate of 'email'" ] +}, { + "name" : "videogame_asset", + "tags" : [ "asset", "console", "controller", "device", "game", "gamepad", "gaming", "playstation", "video" ] +}, { + "name" : "move_to_inbox", + "tags" : [ "archive", "arrow", "down", "email", "envelop", "inbox", "incoming", "letter", "mail", "message", "move to", "send" ] +}, { + "name" : "crop_square", + "tags" : [ "adjust", "adjustments", "app", "application", "area", "components", "crop", "design", "edit", "editing", "expand", "frame", "image", "images", "interface", "open", "photo", "photos", "rectangle", "screen", "settings", "shape", "shapes", "site", "size", "square", "ui", "ux", "web", "website", "window" ] +}, { + "name" : "recent_actors", + "tags" : [ "account", "actors", "avatar", "card", "cards", "carousel", "face", "human", "layers", "list", "people", "person", "profile", "recent", "thumbnail", "user" ] +}, { + "name" : "emoji_nature", + "tags" : [ "animal", "bee", "bug", "daisy", "emoji", "flower", "insect", "ladybug", "nature", "petals", "spring", "summer" ] +}, { + "name" : "cloud_off", + "tags" : [ "app", "application", "backup", "cloud", "connection", "disabled", "drive", "enabled", "files", "folders", "internet", "network", "off", "offline", "on", "sky", "slash", "storage", "upload" ] +}, { + "name" : "panorama_fish_eye", + "tags" : [ "angle", "circle", "eye", "fish", "image", "panorama", "photo", "photography", "picture", "wide" ] +}, { + "name" : "lens", + "tags" : [ "circle", "full", "geometry", "lens", "moon" ] +}, { + "name" : "360", + "tags" : [ "360", "arrow", "av", "camera", "direction", "rotate", "rotation", "vr" ] +}, { + "name" : "share_location", + "tags" : [ "destination", "direction", "gps", "location", "maps", "pin", "place", "share", "stop", "tracking" ] +}, { + "name" : "assignment_late", + "tags" : [ "!", "alert", "assignment", "attention", "caution", "clipboard", "danger", "doc", "document", "error", "exclamation", "important", "late", "mark", "notification", "symbol", "warning" ] +}, { + "name" : "switch_account", + "tags" : [ "account", "choices", "face", "human", "multiple", "options", "people", "person", "profile", "social", "switch", "user" ] +}, { + "name" : "looks_two", + "tags" : [ "2", "digit", "looks", "numbers", "square", "symbol" ] +}, { + "name" : "do_not_disturb", + "tags" : [ "cancel", "close", "denied", "deny", "disturb", "do", "remove", "silence", "stop" ] +}, { + "name" : "donut_small", + "tags" : [ "analytics", "chart", "data", "diagram", "donut", "graph", "infographic", "inprogress", "measure", "metrics", "pie", "small", "statistics", "tracking" ] +}, { + "name" : "saved_search", + "tags" : [ "find", "glass", "important", "look", "magnify", "magnifying", "marked", "saved", "search", "see", "star" ] +}, { + "name" : "contactless", + "tags" : [ "bluetooth", "cash", "connect", "connection", "connectivity", "contact", "contactless", "credit", "device", "finance", "pay", "payment", "signal", "transaction", "wifi", "wireless" ] +}, { + "name" : "highlight_alt", + "tags" : [ "alt", "arrow", "box", "click", "cursor", "draw", "focus", "highlight", "pointer", "select", "selection", "target" ] +}, { + "name" : "assignment_return", + "tags" : [ "arrow", "assignment", "back", "clipboard", "doc", "document", "left", "retun" ] +}, { + "name" : "kitchen", + "tags" : [ "appliance", "cold", "food", "fridge", "home", "house", "ice", "kitchen", "places", "refrigerator", "storage" ] +}, { + "name" : "warehouse", + "tags" : [ "garage", "industry", "manufacturing", "storage", "warehouse" ] +}, { + "name" : "liquor", + "tags" : [ "alcohol", "bar", "bottle", "club", "cocktail", "drink", "food", "liquor", "party", "store", "wine" ] +}, { + "name" : "gpp_maybe", + "tags" : [ "!", "alert", "attention", "caution", "certified", "danger", "error", "exclamation", "gpp", "important", "mark", "maybe", "notification", "privacy", "private", "protect", "protection", "security", "shield", "sim", "symbol", "verified", "warning" ] +}, { + "name" : "settings_input_component", + "tags" : [ "audio", "av", "cable", "cables", "component", "connect", "connection", "connectivity", "input", "internet", "plug", "points", "settings", "video", "wifi" ] +}, { + "name" : "waves", + "tags" : [ "beach", "lake", "ocean", "pool", "river", "sea", "swim", "water", "wave", "waves" ] +}, { + "name" : "hotel_class", + "tags" : [ "achievement", "bookmark", "class", "favorite", "highlight", "hotel", "important", "marked", "rank", "ranking", "rate", "rating", "reward", "save", "saved", "shape", "special", "star" ] +}, { + "name" : "web_asset", + "tags" : [ "-website", "app", "application desktop", "asset", "browser", "design", "download", "image", "interface", "internet", "layout", "screen", "site", "ui", "ux", "video", "web", "website", "window", "www" ] +}, { + "name" : "view_carousel", + "tags" : [ "cards", "carousel", "design", "format", "grid", "layout", "view", "website" ] +}, { + "name" : "anchor", + "tags" : [ "anchor", "google", "logo" ] +}, { + "name" : "filter_alt_off", + "tags" : [ "alt", "disabled", "edit", "filter", "funnel", "off", "offline", "options", "refine", "sift", "slash" ] +}, { + "name" : "balance", + "tags" : [ "balance", "equal", "equity", "impartiality", "justice", "parity", "stability. equilibrium", "steadiness", "symmetry" ] +}, { + "name" : "view_quilt", + "tags" : [ "design", "format", "grid", "layout", "quilt", "square", "squares", "stacked", "view", "website" ] +}, { + "name" : "library_add_check", + "tags" : [ "add", "approve", "check", "collection", "complete", "done", "layers", "library", "mark", "multiple", "music", "ok", "select", "stacked", "tick", "validate", "verified", "video", "yes" ] +}, { + "name" : "queue_music", + "tags" : [ "collection", "list", "music", "playlist", "queue" ] +}, { + "name" : "casino", + "tags" : [ "casino", "dice", "dots", "entertainment", "gamble", "gambling", "game", "games", "luck", "places" ] +}, { + "name" : "hearing", + "tags" : [ "accessibility", "accessible", "aid", "ear", "handicap", "hearing", "help", "impaired", "listen", "sound", "volume" ] +}, { + "name" : "phone_enabled", + "tags" : [ "call", "cell", "contact", "device", "enabled", "hardware", "mobile", "phone", "telephone" ] +}, { + "name" : "linear_scale", + "tags" : [ "app", "application", "components", "design", "interface", "layout", "linear", "measure", "menu", "scale", "screen", "site", "slider", "ui", "ux", "web", "website", "window" ] +}, { + "name" : "holiday_village", + "tags" : [ "architecture", "beach", "camping", "cottage", "estate", "holiday", "home", "house", "lake", "lodge", "maps", "place", "real", "residence", "residential", "stay", "traveling", "vacation", "village" ] +}, { + "name" : "turned_in_not", + "tags" : [ "archive", "bookmark", "favorite", "in", "label", "library", "not", "read", "reading", "remember", "ribbon", "save", "tag", "turned" ] +}, { + "name" : "sync_problem", + "tags" : [ "!", "360", "alert", "around", "arrow", "arrows", "attention", "caution", "danger", "direction", "error", "exclamation", "important", "inprogress", "load", "loading refresh", "mark", "notification", "problem", "renew", "rotate", "symbol", "sync", "turn", "warning" ] +}, { + "name" : "start", + "tags" : [ "arrow", "keyboard", "next", "right", "start" ] +}, { + "name" : "all_inbox", + "tags" : [ "Inbox", "all", "delivered", "delivery", "email", "mail", "message", "send" ] +}, { + "name" : "mediation", + "tags" : [ "arrow", "arrows", "direction", "dots", "mediation", "right" ] +}, { + "name" : "edit_off", + "tags" : [ "compose", "create", "disabled", "draft", "edit", "editing", "enabled", "input", "new", "off", "offline", "on", "pen", "pencil", "slash", "write", "writing" ] +}, { + "name" : "emergency", + "tags" : [ "asterisk", "clinic", "emergency", "health", "hospital", "maps", "medical", "symbol" ] +}, { + "name" : "settings_remote", + "tags" : [ "bluetooth", "connection", "connectivity", "device", "remote", "settings", "signal", "wifi", "wireless" ] +}, { + "name" : "drive_file_move", + "tags" : [ "arrow", "data", "doc", "document", "drive", "file", "folder", "move", "right", "sheet", "slide", "storage" ] +}, { + "name" : "fit_screen", + "tags" : [ "enlarge", "fit", "format", "layout", "reduce", "scale", "screen", "size" ] +}, { + "name" : "hourglass_full", + "tags" : [ "countdown", "full", "hourglass", "loading", "minutes", "time", "wait", "waiting" ] +}, { + "name" : "nights_stay", + "tags" : [ "climate", "cloud", "crescent", "dark", "lunar", "mode", "moon", "nights", "phases", "silence", "silent", "sky", "stay", "time", "weather" ] +}, { + "name" : "pause_circle_filled", + "tags" : [ "circle", "control", "controls", "filled", "media", "music", "pause", "video" ] +}, { + "name" : "catching_pokemon", + "tags" : [ "catching", "go", "pokemon", "pokestop", "travel" ] +}, { + "name" : "king_bed", + "tags" : [ "bed", "bedroom", "double", "furniture", "home", "hotel", "house", "king", "night", "pillows", "queen", "rest", "room", "sleep" ] +}, { + "name" : "flaky", + "tags" : [ "approve", "check", "close", "complete", "contrast", "done", "exit", "flaky", "mark", "no", "ok", "options", "select", "stop", "tick", "verified", "x", "yes" ] +}, { + "name" : "format_size", + "tags" : [ "alphabet", "character", "color", "doc", "edit", "editing", "editor", "fill", "font", "format", "letter", "paint", "sheet", "size", "spreadsheet", "style", "symbol", "text", "type", "writing" ] +}, { + "name" : "interests", + "tags" : [ "circle", "heart", "interests", "shapes", "social", "square", "triangle" ] +}, { + "name" : "stacked_line_chart", + "tags" : [ "analytics", "chart", "data", "diagram", "graph", "infographic", "line", "measure", "metrics", "stacked", "statistics", "tracking" ] +}, { + "name" : "unarchive", + "tags" : [ "archive", "arrow", "inbox", "mail", "store", "unarchive", "undo", "up" ] +}, { + "name" : "subtitles", + "tags" : [ "accessible", "caption", "cc", "character", "closed", "decoder", "language", "media", "movies", "subtitle", "subtitles", "tv" ] +}, { + "name" : "toll", + "tags" : [ "bill", "booth", "car", "card", "cash", "coin", "commerce", "credit", "currency", "dollars", "highway", "money", "online", "pay", "payment", "ticket", "toll" ] +}, { + "name" : "keyboard_double_arrow_up", + "tags" : [ "arrow", "arrows", "direction", "double", "multiple", "navigation", "up" ] +}, { + "name" : "time_to_leave", + "tags" : [ "automobile", "car", "cars", "destination", "direction", "drive", "estimate", "eta", "maps", "public", "transportation", "travel", "trip", "vehicle" ] +}, { + "name" : "location_searching", + "tags" : [ "destination", "direction", "location", "maps", "pin", "place", "pointer", "searching", "stop", "tracking" ] +}, { + "name" : "cable", + "tags" : [ "cable", "connect", "connection", "device", "electronics", "usb", "wire" ] +}, { + "name" : "moving", + "tags" : [ "arrow", "direction", "moving", "navigation", "travel", "up" ] +}, { + "name" : "remove_shopping_cart", + "tags" : [ "card", "cart", "cash", "checkout", "coin", "commerce", "credit", "currency", "disabled", "dollars", "enabled", "off", "on", "online", "pay", "payment", "remove", "shopping", "slash", "tick" ] +}, { + "name" : "cast_for_education", + "tags" : [ "Android", "OS", "airplay", "cast", "chrome", "connect", "desktop", "device", "display", "education", "for", "hardware", "iOS", "learning", "lessons teaching", "mac", "monitor", "screen", "screencast", "streaming", "television", "tv", "web", "window", "wireless" ] +}, { + "name" : "fiber_new", + "tags" : [ "alphabet", "character", "fiber", "font", "letter", "network", "new", "symbol", "text", "type" ] +}, { + "name" : "format_underlined", + "tags" : [ "alphabet", "character", "doc", "edit", "editing", "editor", "font", "format", "letter", "line", "sheet", "spreadsheet", "style", "symbol", "text", "type", "under", "underlined", "writing" ] +}, { + "name" : "pause_circle_outline", + "tags" : [ "circle", "control", "controls", "media", "music", "outline", "pause", "video" ] +}, { + "name" : "mark_chat_unread", + "tags" : [ "bubble", "chat", "circle", "comment", "communicate", "mark", "message", "notification", "speech", "unread" ] +}, { + "name" : "insert_comment", + "tags" : [ "add", "bubble", "chat", "comment", "feedback", "insert", "message" ] +}, { + "name" : "cameraswitch", + "tags" : [ "arrows", "camera", "cameraswitch", "flip", "rotate", "swap", "switch", "view" ] +}, { + "name" : "rocket", + "tags" : [ "rocket", "space", "spaceship" ] +}, { + "name" : "local_airport", + "tags" : [ "air", "airplane", "airport", "flight", "plane", "transportation", "travel", "trip" ] +}, { + "name" : "lock_clock", + "tags" : [ "clock", "date", "lock", "locked", "password", "privacy", "private", "protection", "safety", "schedule", "secure", "security", "time" ] +}, { + "name" : "device_hub", + "tags" : [ "Android", "OS", "circle", "computer", "desktop", "device", "hardware", "hub", "iOS", "laptop", "mobile", "monitor", "phone", "square", "tablet", "triangle", "watch", "wearable", "web" ] +}, { + "name" : "filter_vintage", + "tags" : [ "edit", "editing", "effect", "filter", "flower", "image", "images", "photography", "picture", "pictures", "vintage" ] +}, { + "name" : "sailing", + "tags" : [ "boat", "entertainment", "fishing", "hobby", "ocean", "sailboat", "sailing", "sea", "social sports", "travel", "water" ] +}, { + "name" : "roofing", + "tags" : [ "architecture", "building", "chimney", "construction", "estate", "home", "house", "real", "residence", "residential", "roof", "roofing", "service", "shelter" ] +}, { + "name" : "settings_voice", + "tags" : [ "mic", "microphone", "record", "recorder", "settings", "speaker", "voice" ] +}, { + "name" : "swap_horizontal_circle", + "tags" : [ "arrow", "arrows", "back", "circle", "forward", "horizontal", "swap" ] +}, { + "name" : "add_location_alt", + "tags" : [ "+", "add", "alt", "destination", "direction", "location", "maps", "new", "pin", "place", "plus", "stop", "symbol" ] +}, { + "name" : "room_service", + "tags" : [ "alert", "bell", "delivery", "hotel", "notify", "room", "service" ] +}, { + "name" : "content_paste_search", + "tags" : [ "clipboard", "content", "doc", "document", "file", "find", "paste", "search", "trace", "track" ] +}, { + "name" : "reply_all", + "tags" : [ "all", "arrow", "backward", "group", "left", "mail", "message", "multiple", "reply", "send", "share" ] +}, { + "name" : "compost", + "tags" : [ "bio", "compost", "compostable", "decomposable", "decompose", "eco", "green", "leaf", "leafs", "nature", "organic", "plant", "recycle", "sustainability", "sustainable" ] +}, { + "name" : "bubble_chart", + "tags" : [ "analytics", "bar", "bars", "bubble", "chart", "data", "diagram", "graph", "infographic", "measure", "metrics", "statistics", "tracking" ] +}, { + "name" : "compare", + "tags" : [ "adjust", "adjustment", "compare", "edit", "editing", "edits", "enhance", "fix", "image", "images", "photo", "photography", "photos", "scan", "settings" ] +}, { + "name" : "money_off", + "tags" : [ "bill", "card", "cart", "cash", "coin", "commerce", "credit", "currency", "disabled", "dollars", "enabled", "money", "off", "on", "online", "pay", "payment", "shopping", "slash", "symbol" ] +}, { + "name" : "file_open", + "tags" : [ "arrow", "doc", "document", "drive", "file", "left", "open", "page", "paper" ] +}, { + "name" : "filter_drama", + "tags" : [ "cloud", "drama", "edit", "editing", "effect", "filter", "image", "photo", "photography", "picture", "sky camera" ] +}, { + "name" : "shortcut", + "tags" : [ "arrow", "direction", "forward", "right", "shortcut" ] +}, { + "name" : "view_sidebar", + "tags" : [ "design", "format", "grid", "layout", "sidebar", "view", "web" ] +}, { + "name" : "looks_3", + "tags" : [ "3", "digit", "looks", "numbers", "square", "symbol" ] +}, { + "name" : "note", + "tags" : [ "bookmark", "message", "note", "paper" ] +}, { + "name" : "vertical_align_bottom", + "tags" : [ "align", "alignment", "arrow", "bottom", "doc", "down", "edit", "editing", "editor", "sheet", "spreadsheet", "text", "type", "vertical", "writing" ] +}, { + "name" : "3p", + "tags" : [ "3", "3p", "account", "avatar", "bubble", "chat", "comment", "communicate", "face", "human", "message", "party", "people", "person", "profile", "speech", "user" ] +}, { + "name" : "online_prediction", + "tags" : [ "bulb", "connection", "idea", "light", "network", "online", "prediction", "signal", "wireless" ] +}, { + "name" : "cancel_presentation", + "tags" : [ "cancel", "close", "device", "exit", "no", "present", "presentation", "quit", "remove", "screen", "slide", "stop", "website", "window", "x" ] +}, { + "name" : "select_all", + "tags" : [ "all", "select", "selection", "square", "tool" ] +}, { + "name" : "event_seat", + "tags" : [ "assign", "assigned", "chair", "event", "furniture", "reservation", "row", "seat", "section", "sit" ] +}, { + "name" : "window", + "tags" : [ "close", "glass", "grid", "home", "house", "interior", "layout", "outside", "window" ] +}, { + "name" : "av_timer", + "tags" : [ "av", "clock", "countdown", "duration", "minutes", "seconds", "time", "timer", "watch" ] +}, { + "name" : "album", + "tags" : [ "album", "artist", "audio", "bvb", "cd", "computer", "data", "disk", "file", "music", "record", "sound", "storage", "track" ] +}, { + "name" : "local_dining", + "tags" : [ "dining", "eat", "food", "fork", "knife", "local", "meal", "restaurant", "spoon" ] +}, { + "name" : "headset", + "tags" : [ "accessory", "audio", "device", "ear", "earphone", "headphones", "headset", "listen", "music", "sound" ] +}, { + "name" : "maps_ugc", + "tags" : [ "+", "add", "bubble", "comment", "communicate", "feedback", "maps", "message", "new", "plus", "speech", "symbol", "ugc" ] +}, { + "name" : "airplane_ticket", + "tags" : [ "airplane", "airport", "boarding", "flight", "fly", "maps", "pass", "ticket", "transportation", "travel" ] +}, { + "name" : "vertical_split", + "tags" : [ "design", "format", "grid", "layout", "paragraph", "split", "text", "vertical", "website", "writing" ] +}, { + "name" : "sports_basketball", + "tags" : [ "athlete", "athletic", "ball", "basketball", "entertainment", "exercise", "game", "hobby", "social", "sports" ] +}, { + "name" : "next_plan", + "tags" : [ "arrow", "circle", "next", "plan", "right" ] +}, { + "name" : "drive_folder_upload", + "tags" : [ "arrow", "data", "doc", "document", "drive", "file", "folder", "sheet", "slide", "storage", "up", "upload" ] +}, { + "name" : "pregnant_woman", + "tags" : [ "baby", "birth", "body", "female", "human", "lady", "maternity", "mom", "mother", "people", "person", "pregnant", "women" ] +}, { + "name" : "wallpaper", + "tags" : [ "background", "image", "landscape", "photo", "photography", "picture", "wallpaper" ] +}, { + "name" : "image_search", + "tags" : [ "find", "glass", "image", "landscape", "look", "magnify", "magnifying", "mountain", "mountains", "photo", "photography", "picture", "search", "see" ] +}, { + "name" : "data_exploration", + "tags" : [ "analytics", "arrow", "chart", "data", "diagram", "exploration", "graph", "infographic", "measure", "metrics", "statistics", "tracking" ] +}, { + "name" : "device_thermostat", + "tags" : [ "celsius", "device", "fahrenheit", "meter", "temp", "temperature", "thermometer", "thermostat" ] +}, { + "name" : "healing", + "tags" : [ "bandage", "edit", "editing", "emergency", "fix", "healing", "hospital", "image", "medicine" ] +}, { + "name" : "laptop_mac", + "tags" : [ "Android", "OS", "chrome", "device", "display", "hardware", "iOS", "laptop", "mac", "monitor", "screen", "web", "window" ] +}, { + "name" : "height", + "tags" : [ "arrow", "color", "doc", "down", "edit", "editing", "editor", "fill", "format", "height", "paint", "sheet", "spreadsheet", "style", "text", "type", "up", "writing" ] +}, { + "name" : "restore_from_trash", + "tags" : [ "arrow", "back", "backwards", "clock", "date", "history", "refresh", "renew", "restore", "reverse", "rotate", "schedule", "time", "turn" ] +}, { + "name" : "radar", + "tags" : [ "detect", "military", "near", "network", "position", "radar", "scan" ] +}, { + "name" : "auto_awesome_motion", + "tags" : [ "adjust", "auto", "awesome", "collage", "edit", "editing", "enhance", "image", "motion", "photo", "video" ] +}, { + "name" : "file_download_done", + "tags" : [ "arrow", "arrows", "check", "done", "down", "download", "downloads", "drive", "file", "install", "installed", "tick", "upload" ] +}, { + "name" : "notification_add", + "tags" : [ "+", "active", "add", "alarm", "alert", "bell", "chime", "notification", "notifications", "notify", "plus", "reminder", "ring", "sound", "symbol" ] +}, { + "name" : "call_made", + "tags" : [ "arrow", "call", "device", "made", "mobile" ] +}, { + "name" : "camera_enhance", + "tags" : [ "ai", "artificial", "automatic", "automation", "camera", "custom", "enhance", "genai", "important", "intelligence", "lens", "magic", "photo", "photography", "picture", "quality", "smart", "spark", "sparkle", "special", "star" ] +}, { + "name" : "rotate_left", + "tags" : [ "around", "arrow", "direction", "inprogress", "left", "load", "loading refresh", "renew", "rotate", "turn" ] +}, { + "name" : "local_taxi", + "tags" : [ "automobile", "cab", "call", "car", "cars", "direction", "local", "lyft", "maps", "public", "taxi", "transportation", "uber", "vehicle", "yellow" ] +}, { + "name" : "star_border_purple500", + "tags" : [ "500", "best", "bookmark", "border", "favorite", "highlight", "outline", "purple", "ranking", "rate", "rating", "save", "star", "toggle" ] +}, { + "name" : "gpp_bad", + "tags" : [ "bad", "cancel", "certified", "close", "error", "exit", "gpp", "no", "privacy", "private", "protect", "protection", "remove", "security", "shield", "sim", "stop", "verified", "x" ] +}, { + "name" : "playlist_play", + "tags" : [ "arrow", "collection", "list", "music", "play", "playlist" ] +}, { + "name" : "cast", + "tags" : [ "Android", "OS", "airplay", "cast", "chrome", "connect", "desktop", "device", "display", "hardware", "iOS", "mac", "monitor", "screen", "screencast", "streaming", "television", "tv", "web", "window", "wireless" ] +}, { + "name" : "vertical_align_top", + "tags" : [ "align", "alignment", "arrow", "doc", "edit", "editing", "editor", "sheet", "spreadsheet", "text", "top", "type", "up", "vertical", "writing" ] +}, { + "name" : "ramen_dining", + "tags" : [ "breakfast", "dining", "dinner", "drink", "fastfood", "food", "lunch", "meal", "noodles", "ramen", "restaurant" ] +}, { + "name" : "data_usage", + "tags" : [ "analytics", "chart", "data", "diagram", "graph", "infographic", "measure", "metrics", "statistics", "tracking", "usage" ] +}, { + "name" : "markunread_mailbox", + "tags" : [ "deliver", "envelop", "letter", "mail", "mailbox", "markunread", "post", "postal", "postbox", "receive", "send", "unread" ] +}, { + "name" : "terminal", + "tags" : [ "application", "code", "emulator", "program", "software", "terminal" ] +}, { + "name" : "screen_share", + "tags" : [ "Android", "OS", "arrow", "cast", "chrome", "device", "display", "hardware", "iOS", "laptop", "mac", "mirror", "monitor", "screen", "share", "steam", "streaming", "web", "window" ] +}, { + "name" : "center_focus_strong", + "tags" : [ "camera", "center", "focus", "image", "lens", "photo", "photography", "strong", "zoom" ] +}, { + "name" : "queue", + "tags" : [ "add", "collection", "layers", "list", "multiple", "music", "playlist", "queue", "stack", "stream", "video" ] +}, { + "name" : "games", + "tags" : [ "adjust", "arrow", "arrows", "control", "controller", "direction", "games", "gaming", "left", "move", "right" ] +}, { + "name" : "low_priority", + "tags" : [ "arrange", "arrow", "backward", "bottom", "list", "low", "move", "order", "priority" ] +}, { + "name" : "dynamic_form", + "tags" : [ "bolt", "code", "dynamic", "electric", "fast", "form", "lightning", "lists", "questionnaire", "thunderbolt" ] +}, { + "name" : "tab", + "tags" : [ "browser", "computer", "document", "documents", "folder", "internet", "tab", "tabs", "web", "website", "window", "windows" ] +}, { + "name" : "lock_reset", + "tags" : [ "around", "inprogress", "load", "loading refresh", "lock", "locked", "password", "privacy", "private", "protection", "renew", "rotate", "safety", "secure", "security", "turn" ] +}, { + "name" : "room_preferences", + "tags" : [ "building", "door", "doorway", "entrance", "gear", "home", "house", "interior", "office", "open", "preferences", "room", "settings" ] +}, { + "name" : "crop", + "tags" : [ "adjust", "adjustments", "area", "crop", "edit", "editing", "frame", "image", "images", "photo", "photos", "rectangle", "settings", "size", "square" ] +}, { + "name" : "monitor_weight", + "tags" : [ "body", "device", "diet", "health", "monitor", "scale", "smart", "weight" ] +}, { + "name" : "trip_origin", + "tags" : [ "circle", "departure", "origin", "trip" ] +}, { + "name" : "calendar_view_week", + "tags" : [ "calendar", "date", "day", "event", "format", "grid", "layout", "month", "schedule", "today", "view", "week" ] +}, { + "name" : "signal_wifi_4_bar", + "tags" : [ "4", "bar", "cell", "cellular", "data", "internet", "mobile", "network", "phone", "signal", "wifi", "wireless" ] +}, { + "name" : "blur_on", + "tags" : [ "blur", "disabled", "dots", "edit", "editing", "effect", "enabled", "enhance", "filter", "off", "on", "slash" ] +}, { + "name" : "view_stream", + "tags" : [ "design", "format", "grid", "layout", "lines", "list", "stacked", "stream", "view", "website" ] +}, { + "name" : "radio", + "tags" : [ "antenna", "audio", "device", "frequency", "hardware", "listen", "media", "music", "player", "radio", "signal", "tune" ] +}, { + "name" : "hail", + "tags" : [ "body", "hail", "human", "people", "person", "pick", "public", "stop", "taxi", "transportation" ] +}, { + "name" : "do_disturb_on", + "tags" : [ "cancel", "close", "denied", "deny", "disabled", "disturb", "do", "enabled", "off", "on", "remove", "silence", "slash", "stop" ] +}, { + "name" : "sensor_door", + "tags" : [ "alarm", "security", "security system" ] +}, { + "name" : "wb_incandescent", + "tags" : [ "balance", "bright", "edit", "editing", "incandescent", "light", "lighting", "setting", "settings", "white", "wp" ] +}, { + "name" : "local_drink", + "tags" : [ "cup", "drink", "drop", "droplet", "liquid", "local", "park", "water" ] +}, { + "name" : "accessible_forward", + "tags" : [ "accessibility", "accessible", "body", "forward", "handicap", "help", "human", "people", "person", "wheelchair" ] +}, { + "name" : "replay_circle_filled", + "tags" : [ "arrow", "arrows", "circle", "control", "controls", "filled", "music", "refresh", "renew", "repeat", "replay", "video" ] +}, { + "name" : "local_printshop", + "tags" : [ "draft", "fax", "ink", "local", "machine", "office", "paper", "print", "printer", "printshop", "send" ] +}, { + "name" : "local_laundry_service", + "tags" : [ "cleaning", "clothing", "dry", "dryer", "hotel", "laundry", "local", "service", "washer" ] +}, { + "name" : "vpn_lock", + "tags" : [ "earth", "globe", "lock", "locked", "network", "password", "privacy", "private", "protection", "safety", "secure", "security", "virtual", "vpn", "world" ] +}, { + "name" : "schema", + "tags" : [ "analytics", "chart", "data", "diagram", "flow", "graph", "infographic", "measure", "metrics", "schema", "statistics", "tracking" ] +}, { + "name" : "request_page", + "tags" : [ "data", "doc", "document", "drive", "file", "folder", "folders", "page", "paper", "request", "sheet", "slide", "writing" ] +}, { + "name" : "token", + "tags" : [ "badge", "hexagon", "mark", "shield", "sign", "symbol" ] +}, { + "name" : "branding_watermark", + "tags" : [ "branding", "components", "copyright", "design", "emblem", "format", "identity", "interface", "layout", "logo", "screen", "site", "stamp", "ui", "ux", "watermark", "web", "website", "window" ] +}, { + "name" : "theater_comedy", + "tags" : [ "broadway", "comedy", "event", "movie", "musical", "places", "show", "standup", "theater", "tour", "watch" ] +}, { + "name" : "text_format", + "tags" : [ "alphabet", "character", "font", "format", "letter", "square A", "style", "symbol", "text", "type" ] +}, { + "name" : "directions_bus_filled", + "tags" : [ "automobile", "bus", "car", "cars", "direction", "directions", "filled", "maps", "public", "transportation", "vehicle" ] +}, { + "name" : "remove_done", + "tags" : [ "approve", "check", "complete", "disabled", "done", "enabled", "finished", "mark", "multiple", "off", "ok", "on", "remove", "select", "slash", "tick", "yes" ] +}, { + "name" : "sports_bar", + "tags" : [ "alcohol", "bar", "beer", "drink", "liquor", "pint", "places", "pub", "sports" ] +}, { + "name" : "watch", + "tags" : [ "Android", "OS", "ar", "clock", "gadget", "iOS", "time", "vr", "watch", "wearables", "web", "wristwatch" ] +}, { + "name" : "add_to_drive", + "tags" : [ "add", "app", "application", "backup", "cloud", "drive", "files", "folders", "gdrive", "google", "recovery", "shortcut", "storage" ] +}, { + "name" : "format_align_center", + "tags" : [ "align", "alignment", "center", "doc", "edit", "editing", "editor", "format", "sheet", "spreadsheet", "text", "type", "writing" ] +}, { + "name" : "settings_power", + "tags" : [ "info", "information", "off", "on", "power", "save", "settings", "shutdown" ] +}, { + "name" : "local_pizza", + "tags" : [ "drink", "fastfood", "food", "local", "meal", "pizza" ] +}, { + "name" : "add_alert", + "tags" : [ "+", "active", "add", "alarm", "alert", "bell", "chime", "new", "notifications", "notify", "plus", "reminder", "ring", "sound", "symbol" ] +}, { + "name" : "smart_button", + "tags" : [ "action", "ai", "artificial", "automatic", "automation", "button", "components", "composer", "custom", "function", "genai", "intelligence", "interface", "magic", "site", "smart", "spark", "sparkle", "special", "star", "stars", "ui", "ux", "web", "website" ] +}, { + "name" : "flare", + "tags" : [ "bright", "edit", "editing", "effect", "flare", "image", "images", "light", "photography", "picture", "pictures", "sun" ] +}, { + "name" : "developer_mode", + "tags" : [ "Android", "OS", "bracket", "cell", "code", "developer", "development", "device", "engineer", "hardware", "iOS", "mobile", "mode", "phone", "tablet" ] +}, { + "name" : "call_split", + "tags" : [ "arrow", "call", "device", "mobile", "split" ] +}, { + "name" : "free_breakfast", + "tags" : [ "beverage", "breakfast", "cafe", "coffee", "cup", "drink", "free", "mug", "tea" ] +}, { + "name" : "auto_delete", + "tags" : [ "auto", "bin", "can", "clock", "date", "delete", "garbage", "remove", "schedule", "time", "trash" ] +}, { + "name" : "sports_kabaddi", + "tags" : [ "athlete", "athletic", "body", "combat", "entertainment", "exercise", "fighting", "game", "hobby", "human", "kabaddi", "people", "person", "social", "sports", "wrestle", "wrestling" ] +}, { + "name" : "face_retouching_natural", + "tags" : [ "ai", "artificial", "automatic", "automation", "custom", "edit", "editing", "effect", "emoji", "emotion", "face", "faces", "genai", "image", "intelligence", "magic", "natural", "photo", "photography", "retouch", "retouching", "settings", "smart", "spark", "sparkle", "star", "tag" ] +}, { + "name" : "not_listed_location", + "tags" : [ "?", "assistance", "destination", "direction", "help", "info", "information", "listed", "location", "maps", "not", "pin", "place", "punctuation", "question mark", "stop", "support", "symbol" ] +}, { + "name" : "wb_cloudy", + "tags" : [ "balance", "cloud", "cloudy", "edit", "editing", "white", "wp" ] +}, { + "name" : "sports", + "tags" : [ "athlete", "athletic", "blowing", "coach", "entertainment", "exercise", "game", "hobby", "instrument", "referee", "social", "sound", "sports", "warning", "whistle" ] +}, { + "name" : "emoji_symbols", + "tags" : [ "ampersand", "character", "emoji", "hieroglyph", "music", "note", "percent", "sign", "symbols" ] +}, { + "name" : "bathtub", + "tags" : [ "bath", "bathing", "bathroom", "bathtub", "home", "hotel", "human", "person", "shower", "travel", "tub" ] +}, { + "name" : "forward_10", + "tags" : [ "10", "arrow", "control", "controls", "digit", "fast", "forward", "music", "number", "play", "seconds", "symbol", "video" ] +}, { + "name" : "tablet_mac", + "tags" : [ "Android", "OS", "device", "hardware", "iOS", "ipad", "mobile", "tablet mac", "web" ] +}, { + "name" : "mode_night", + "tags" : [ "dark", "disturb", "lunar", "mode", "moon", "night", "sleep" ] +}, { + "name" : "broken_image", + "tags" : [ "broken", "corrupt", "error", "image", "landscape", "mountain", "mountains", "photo", "photography", "picture", "torn" ] +}, { + "name" : "escalator_warning", + "tags" : [ "body", "child", "escalator", "human", "kid", "parent", "people", "person", "warning" ] +}, { + "name" : "assistant", + "tags" : [ "ai", "artificial", "assistant", "automatic", "automation", "bubble", "chat", "comment", "communicate", "custom", "feedback", "genai", "intelligence", "magic", "message", "recommendation", "smart", "spark", "sparkle", "speech", "star", "suggestion", "twinkle" ] +}, { + "name" : "cases", + "tags" : [ "bag", "baggage", "briefcase", "business", "case", "cases", "purse", "suitcase" ] +}, { + "name" : "wifi_tethering", + "tags" : [ "cell", "cellular", "connection", "data", "internet", "mobile", "network", "phone", "scan", "service", "signal", "speed", "tethering", "wifi", "wireless" ] +}, { + "name" : "reduce_capacity", + "tags" : [ "arrow", "body", "capacity", "covid", "decrease", "down", "human", "people", "person", "reduce", "social" ] +}, { + "name" : "colorize", + "tags" : [ "color", "colorize", "dropper", "extract", "eye", "picker", "tool" ] +}, { + "name" : "save_as", + "tags" : [ "compose", "create", "data", "disk", "document", "draft", "drive", "edit", "editing", "file", "floppy", "input", "multimedia", "pen", "pencil", "save", "storage", "write", "writing" ] +}, { + "name" : "card_travel", + "tags" : [ "bill", "card", "cash", "coin", "commerce", "cost", "credit", "currency", "dollars", "finance", "membership", "miles", "money", "online", "pay", "payment", "travel", "trip" ] +}, { + "name" : "emoji_food_beverage", + "tags" : [ "beverage", "coffee", "cup", "drink", "emoji", "mug", "plate", "set", "tea" ] +}, { + "name" : "font_download", + "tags" : [ "A", "alphabet", "character", "download", "font", "letter", "square", "symbol", "text", "type" ] +}, { + "name" : "outbox", + "tags" : [ "box", "mail", "outbox", "send", "sent" ] +}, { + "name" : "battery_std", + "tags" : [ "battery", "cell", "charge", "mobile", "plus", "power", "standard", "std" ] +}, { + "name" : "sick", + "tags" : [ "covid", "discomfort", "emotions", "expressions", "face", "feelings", "fever", "flu", "ill", "mood", "pain", "person", "sick", "survey", "upset" ] +}, { + "name" : "add_location", + "tags" : [ "+", "add", "destination", "direction", "location", "maps", "new", "pin", "place", "plus", "stop", "symbol" ] +}, { + "name" : "try", + "tags" : [ "bookmark", "bubble", "chat", "comment", "communicate", "favorite", "feedback", "highlight", "important", "marked", "message", "save", "saved", "shape", "special", "speech", "star", "try" ] +}, { + "name" : "discount", + "tags" : [ ] +}, { + "name" : "man", + "tags" : [ "boy", "gender", "male", "man", "social", "symbol" ] +}, { + "name" : "running_with_errors", + "tags" : [ "!", "alert", "attention", "caution", "danger", "duration", "error", "errors", "exclamation", "important", "mark", "notification", "process", "processing", "running", "symbol", "time", "warning", "with" ] +}, { + "name" : "diversity_3", + "tags" : [ "committee", "diverse", "diversity", "family", "friends", "group", "groups", "humans", "network", "people", "persons", "social", "team" ] +}, { + "name" : "filter_none", + "tags" : [ "filter", "multiple", "none", "square", "stack" ] +}, { + "name" : "cloud_sync", + "tags" : [ "app", "application", "around", "backup", "cloud", "connection", "drive", "files", "folders", "inprogress", "internet", "load", "loading refresh", "network", "renew", "rotate", "sky", "storage", "turn", "upload" ] +}, { + "name" : "bloodtype", + "tags" : [ "blood", "bloodtype", "donate", "droplet", "emergency", "hospital", "medicine", "negative", "positive", "type", "water" ] +}, { + "name" : "dinner_dining", + "tags" : [ "breakfast", "dining", "dinner", "food", "fork", "lunch", "meal", "restaurant", "spaghetti", "utensils" ] +}, { + "name" : "transfer_within_a_station", + "tags" : [ "a", "arrow", "arrows", "body", "direction", "human", "left", "maps", "people", "person", "public", "right", "route", "station", "stop", "transfer", "transportation", "vehicle", "walk", "within" ] +}, { + "name" : "weekend", + "tags" : [ "chair", "couch", "furniture", "home", "living", "lounge", "relax", "room", "weekend" ] +}, { + "name" : "child_friendly", + "tags" : [ "baby", "care", "carriage", "child", "children", "friendly", "infant", "kid", "newborn", "stroller", "toddler", "young" ] +}, { + "name" : "offline_pin", + "tags" : [ "approve", "check", "checkmark", "circle", "complete", "done", "mark", "offline", "ok", "pin", "select", "tick", "validate", "verified", "yes" ] +}, { + "name" : "replay_10", + "tags" : [ "10", "arrow", "arrows", "control", "controls", "digit", "music", "number", "refresh", "renew", "repeat", "replay", "symbol", "ten", "video" ] +}, { + "name" : "brightness_4", + "tags" : [ "4", "brightness", "circle", "control", "crescent", "level", "moon", "screen", "sun" ] +}, { + "name" : "cruelty_free", + "tags" : [ "animal", "bunny", "cruelty", "eco", "free", "nature", "rabbit", "social", "sustainability", "sustainable", "testing" ] +}, { + "name" : "format_paint", + "tags" : [ "brush", "color", "doc", "edit", "editing", "editor", "fill", "format", "paint", "roller", "sheet", "spreadsheet", "style", "text", "type", "writing" ] +}, { + "name" : "filter_center_focus", + "tags" : [ "camera", "center", "dot", "edit", "filter", "focus", "image", "photo", "photography", "picture" ] +}, { + "name" : "area_chart", + "tags" : [ "analytics", "area", "chart", "data", "diagram", "graph", "infographic", "measure", "metrics", "statistics", "tracking" ] +}, { + "name" : "bakery_dining", + "tags" : [ "bakery", "bread", "breakfast", "brunch", "croissant", "dining", "food" ] +}, { + "name" : "emoji_transportation", + "tags" : [ "architecture", "automobile", "building", "car", "cars", "direction", "emoji", "estate", "maps", "place", "public", "real", "residence", "residential", "shelter", "transportation", "travel", "vehicle" ] +}, { + "name" : "folder_special", + "tags" : [ "bookmark", "data", "doc", "document", "drive", "favorite", "file", "folder", "highlight", "important", "marked", "save", "saved", "shape", "sheet", "slide", "special", "star", "storage" ] +}, { + "name" : "door_front", + "tags" : [ "closed", "door", "doorway", "entrance", "exit", "front", "home", "house", "way" ] +}, { + "name" : "calendar_view_day", + "tags" : [ "calendar", "date", "day", "event", "format", "grid", "layout", "month", "schedule", "today", "view", "week" ] +}, { + "name" : "legend_toggle", + "tags" : [ "analytics", "chart", "data", "diagram", "graph", "infographic", "legend", "measure", "metrics", "monitoring", "stackdriver", "statistics", "toggle", "tracking" ] +}, { + "name" : "light", + "tags" : [ "bulb", "ceiling", "hanging", "inside", "interior", "lamp", "light", "lighting", "pendent", "room" ] +}, { + "name" : "find_replace", + "tags" : [ "around", "arrows", "find", "glass", "inprogress", "load", "loading refresh", "look", "magnify", "magnifying", "renew", "replace", "rotate", "search", "see" ] +}, { + "name" : "crop_original", + "tags" : [ "adjust", "adjustments", "area", "crop", "edit", "editing", "frame", "image", "images", "original", "photo", "photos", "picture", "settings", "size" ] +}, { + "name" : "rowing", + "tags" : [ "activity", "boat", "body", "canoe", "human", "people", "person", "row", "rowing", "sport", "water" ] +}, { + "name" : "enhanced_encryption", + "tags" : [ "+", "add", "encryption", "enhanced", "lock", "locked", "new", "password", "plus", "privacy", "private", "protection", "safety", "secure", "security", "symbol" ] +}, { + "name" : "how_to_vote", + "tags" : [ "ballot", "election", "how", "poll", "to", "vote" ] +}, { + "name" : "chrome_reader_mode", + "tags" : [ "chrome", "mode", "read", "reader", "text" ] +}, { + "name" : "auto_fix_normal", + "tags" : [ "ai", "artificial", "auto", "automatic", "automation", "custom", "edit", "erase", "fix", "genai", "intelligence", "magic", "modify", "smart", "spark", "sparkle", "star", "wand" ] +}, { + "name" : "compress", + "tags" : [ "arrow", "arrows", "collide", "compress", "pressure", "push", "together" ] +}, { + "name" : "dehaze", + "tags" : [ "adjust", "dehaze", "edit", "editing", "enhance", "haze", "image", "lines", "photo", "photography", "remove" ] +}, { + "name" : "outlet", + "tags" : [ "connect", "connecter", "electricity", "outlet", "plug", "power" ] +}, { + "name" : "desktop_mac", + "tags" : [ "Android", "OS", "chrome", "desktop", "device", "display", "hardware", "iOS", "mac", "monitor", "screen", "web", "window" ] +}, { + "name" : "nature_people", + "tags" : [ "activity", "body", "forest", "human", "nature", "outdoor", "outside", "park", "people", "person", "tree", "wilderness" ] +}, { + "name" : "sports_tennis", + "tags" : [ "athlete", "athletic", "ball", "bat", "entertainment", "exercise", "game", "hobby", "racket", "social", "sports", "tennis" ] +}, { + "name" : "forest", + "tags" : [ "forest", "jungle", "nature", "plantation", "plants", "trees", "woodland" ] +}, { + "name" : "upcoming", + "tags" : [ "alarm", "calendar", "mail", "message", "notification", "upcoming" ] +}, { + "name" : "assignment_returned", + "tags" : [ "arrow", "assignment", "clipboard", "doc", "document", "down", "returned" ] +}, { + "name" : "cookie", + "tags" : [ "biscuit", "cookies", "data", "dessert", "wafer" ] +}, { + "name" : "fax", + "tags" : [ "fax", "machine", "office", "phone", "send" ] +}, { + "name" : "square", + "tags" : [ "draw", "four", "shape quadrangle", "sides", "square" ] +}, { + "name" : "density_medium", + "tags" : [ "density", "horizontal", "lines", "medium", "rule", "rules" ] +}, { + "name" : "terrain", + "tags" : [ "geography", "landscape", "mountain", "terrain" ] +}, { + "name" : "settings_brightness", + "tags" : [ "brightness", "dark", "filter", "light", "mode", "setting", "settings" ] +}, { + "name" : "attach_email", + "tags" : [ "attach", "attachment", "clip", "compose", "email", "envelop", "letter", "link", "mail", "message", "send" ] +}, { + "name" : "photo", + "tags" : [ "image", "mountain", "mountains", "photo", "photography", "picture" ] +}, { + "name" : "http", + "tags" : [ "alphabet", "character", "font", "http", "letter", "symbol", "text", "transfer", "type", "url", "website" ] +}, { + "name" : "garage", + "tags" : [ "automobile", "automotive", "car", "cars", "direction", "garage", "maps", "transportation", "travel", "vehicle" ] +}, { + "name" : "wine_bar", + "tags" : [ "alcohol", "bar", "cocktail", "cup", "drink", "glass", "liquor", "wine" ] +}, { + "name" : "multiple_stop", + "tags" : [ "arrows", "directions", "dots", "left", "maps", "multiple", "navigation", "right", "stop" ] +}, { + "name" : "format_color_text", + "tags" : [ "color", "doc", "edit", "editing", "editor", "fill", "format", "paint", "sheet", "spreadsheet", "style", "text", "type", "writing" ] +}, { + "name" : "gesture", + "tags" : [ "drawing", "finger", "gesture", "gestures", "hand", "motion" ] +}, { + "name" : "heart_broken", + "tags" : [ "break", "broken", "core", "crush", "health", "heart", "nucleus", "split" ] +}, { + "name" : "format_align_right", + "tags" : [ "align", "alignment", "doc", "edit", "editing", "editor", "format", "right", "sheet", "spreadsheet", "text", "type", "writing" ] +}, { + "name" : "transgender", + "tags" : [ "female", "gender", "lgbt", "male", "neutral", "social", "symbol", "transgender" ] +}, { + "name" : "alarm_add", + "tags" : [ "+", "add", "alarm", "alert", "bell", "clock", "countdown", "date", "new", "notification", "plus", "schedule", "symbol", "time" ] +}, { + "name" : "new_label", + "tags" : [ "+", "add", "archive", "bookmark", "favorite", "label", "library", "new", "plus", "read", "reading", "remember", "ribbon", "save", "symbol", "tag" ] +}, { + "name" : "south_east", + "tags" : [ "arrow", "directional", "down", "east", "maps", "navigation", "right", "south" ] +}, { + "name" : "backup_table", + "tags" : [ "backup", "drive", "files folders", "format", "layout", "stack", "storage", "table" ] +}, { + "name" : "unsubscribe", + "tags" : [ "cancel", "close", "email", "envelop", "letter", "mail", "message", "newsletter", "off", "remove", "send", "subscribe", "unsubscribe" ] +}, { + "name" : "flash_off", + "tags" : [ "bolt", "disabled", "electric", "enabled", "fast", "flash", "lightning", "off", "on", "slash", "thunderbolt" ] +}, { + "name" : "elderly", + "tags" : [ "body", "cane", "elderly", "human", "old", "people", "person", "senior" ] +}, { + "name" : "generating_tokens", + "tags" : [ "access", "ai", "api", "artificial", "automatic", "automation", "coin", "custom", "genai", "generating", "intelligence", "magic", "smart", "spark", "sparkle", "star", "tokens" ] +}, { + "name" : "spellcheck", + "tags" : [ "a", "alphabet", "approve", "character", "check", "font", "letter", "mark", "ok", "processor", "select", "spell", "spellcheck", "symbol", "text", "tick", "type", "word", "write", "yes" ] +}, { + "name" : "auto_awesome_mosaic", + "tags" : [ "adjust", "auto", "awesome", "collage", "edit", "editing", "enhance", "image", "mosaic", "photo" ] +}, { + "name" : "outdoor_grill", + "tags" : [ "barbecue", "bbq", "charcoal", "cooking", "grill", "home", "house", "outdoor", "outside" ] +}, { + "name" : "restore_page", + "tags" : [ "arrow", "data", "doc", "file", "page", "paper", "refresh", "restore", "rotate", "sheet", "storage" ] +}, { + "name" : "foundation", + "tags" : [ "architecture", "base", "basis", "building", "construction", "estate", "foundation", "home", "house", "real", "residential" ] +}, { + "name" : "credit_card_off", + "tags" : [ "card", "charge", "commerce", "cost", "credit", "disabled", "enabled", "finance", "money", "off", "online", "pay", "payment", "slash" ] +}, { + "name" : "scatter_plot", + "tags" : [ "analytics", "bar", "bars", "chart", "circles", "data", "diagram", "dot", "graph", "infographic", "measure", "metrics", "plot", "scatter", "statistics", "tracking" ] +}, { + "name" : "signal_cellular_4_bar", + "tags" : [ "4", "bar", "cell", "cellular", "data", "internet", "mobile", "network", "phone", "signal", "speed", "wifi", "wireless" ] +}, { + "name" : "add_moderator", + "tags" : [ "+", "add", "certified", "moderator", "new", "plus", "privacy", "private", "protect", "protection", "security", "shield", "symbol", "verified" ] +}, { + "name" : "play_for_work", + "tags" : [ "arrow", "circle", "down", "google", "half", "play", "work" ] +}, { + "name" : "add_card", + "tags" : [ "+", "add", "bill", "card", "cash", "coin", "commerce", "cost", "credit", "currency", "dollars", "finance", "money", "new", "online", "pay", "payment", "plus", "price", "shopping", "symbol" ] +}, { + "name" : "app_settings_alt", + "tags" : [ "Android", "OS", "app", "applications", "cell", "device", "gear", "hardware", "iOS", "mobile", "phone", "setting", "settings", "tablet" ] +}, { + "name" : "keyboard_tab", + "tags" : [ "arrow", "keyboard", "left", "next", "right", "tab" ] +}, { + "name" : "wifi_protected_setup", + "tags" : [ "around", "arrow", "arrows", "protected", "rotate", "setup", "wifi" ] +}, { + "name" : "deck", + "tags" : [ "chairs", "deck", "home", "house", "outdoors", "outside", "patio", "social", "terrace", "umbrella", "yard" ] +}, { + "name" : "takeout_dining", + "tags" : [ "box", "container", "delivery", "dining", "food", "meal", "restaurant", "takeout" ] +}, { + "name" : "tag_faces", + "tags" : [ "emoji", "emotion", "faces", "happy", "satisfied", "smile", "tag" ] +}, { + "name" : "brightness_6", + "tags" : [ "6", "brightness", "circle", "control", "crescent", "level", "moon", "screen", "sun" ] +}, { + "name" : "woman", + "tags" : [ "female", "gender", "girl", "lady", "social", "symbol", "woman", "women" ] +}, { + "name" : "assistant_direction", + "tags" : [ "assistant", "destination", "direction", "location", "maps", "navigate", "navigation", "pin", "place", "right", "stop" ] +}, { + "name" : "brightness_5", + "tags" : [ "5", "brightness", "circle", "control", "crescent", "level", "moon", "screen", "sun" ] +}, { + "name" : "social_distance", + "tags" : [ "6", "apart", "body", "distance", "ft", "human", "people", "person", "social", "space" ] +}, { + "name" : "free_cancellation", + "tags" : [ "approve", "calendar", "cancel", "cancellation", "check", "complete", "date", "day", "done", "event", "exit", "free", "mark", "month", "no", "ok", "remove", "schedule", "select", "stop", "tick", "validate", "verified", "x", "yes" ] +}, { + "name" : "subdirectory_arrow_left", + "tags" : [ "arrow", "directory", "down", "left", "navigation", "sub", "subdirectory" ] +}, { + "name" : "laptop_chromebook", + "tags" : [ "Android", "OS", "chrome", "chromebook", "device", "display", "hardware", "iOS", "laptop", "mac chromebook", "monitor", "screen", "web", "window" ] +}, { + "name" : "format_list_numbered_rtl", + "tags" : [ "align", "alignment", "digit", "doc", "edit", "editing", "editor", "format", "list", "notes", "number", "numbered", "rtl", "sheet", "spreadsheet", "symbol", "text", "type", "writing" ] +}, { + "name" : "store_mall_directory", + "tags" : [ "directory", "mall", "store" ] +}, { + "name" : "settings_overscan", + "tags" : [ "arrows", "expand", "image", "photo", "picture", "scan", "settings" ] +}, { + "name" : "icecream", + "tags" : [ "cream", "dessert", "food", "ice", "icecream", "snack" ] +}, { + "name" : "details", + "tags" : [ "details", "edit", "editing", "enhance", "image", "photo", "photography", "sharpen", "triangle" ] +}, { + "name" : "add_reaction", + "tags" : [ "+", "add", "emoji", "emotions", "expressions", "face", "feelings", "glad", "happiness", "happy", "icon", "icons", "insert", "like", "mood", "new", "person", "pleased", "plus", "smile", "smiling", "social", "survey", "symbol" ] +}, { + "name" : "follow_the_signs", + "tags" : [ "arrow", "body", "directional", "follow", "human", "people", "person", "right", "signs", "social", "the" ] +}, { + "name" : "attribution", + "tags" : [ "attribute", "attribution", "body", "copyright", "copywriter", "human", "people", "person" ] +}, { + "name" : "food_bank", + "tags" : [ "architecture", "bank", "building", "charity", "eat", "estate", "food", "fork", "house", "knife", "meal", "place", "real", "residence", "residential", "shelter", "utensils" ] +}, { + "name" : "closed_caption", + "tags" : [ "accessible", "alphabet", "caption", "cc", "character", "closed", "decoder", "font", "language", "letter", "media", "movies", "subtitle", "subtitles", "symbol", "text", "tv", "type" ] +}, { + "name" : "gif", + "tags" : [ "alphabet", "animated", "animation", "bitmap", "character", "font", "format", "gif", "graphics", "interchange", "letter", "symbol", "text", "type" ] +}, { + "name" : "phonelink", + "tags" : [ "Android", "OS", "chrome", "computer", "connect", "desktop", "device", "hardware", "iOS", "link", "mac", "mobile", "phone", "phonelink", "sync", "tablet", "web", "windows" ] +}, { + "name" : "grain", + "tags" : [ "dots", "edit", "editing", "effect", "filter", "grain", "image", "images", "photography", "picture", "pictures" ] +}, { + "name" : "personal_injury", + "tags" : [ "accident", "aid", "arm", "bandage", "body", "broke", "cast", "fracture", "health", "human", "injury", "medical", "patient", "people", "person", "personal", "sling", "social" ] +}, { + "name" : "flip_camera_android", + "tags" : [ "android", "camera", "center", "edit", "editing", "flip", "image", "mobile", "orientation", "rotate", "turn" ] +}, { + "name" : "museum", + "tags" : [ "architecture", "attraction", "building", "estate", "event", "exhibition", "explore", "local", "museum", "places", "real", "see", "shop", "store", "tour" ] +}, { + "name" : "north_west", + "tags" : [ "arrow", "directional", "left", "maps", "navigation", "north", "up", "west" ] +}, { + "name" : "gite", + "tags" : [ "architecture", "estate", "gite", "home", "hostel", "house", "maps", "place", "real", "residence", "residential", "stay", "traveling" ] +}, { + "name" : "highlight", + "tags" : [ "color", "doc", "edit", "editing", "editor", "emphasize", "fill", "flash", "format", "highlight", "light", "paint", "sheet", "spreadsheet", "style", "text", "type", "writing" ] +}, { + "name" : "brightness_1", + "tags" : [ "1", "brightness", "circle", "control", "crescent", "level", "moon", "screen" ] +}, { + "name" : "plus_one", + "tags" : [ "1", "add", "digit", "increase", "number", "one", "plus", "symbol" ] +}, { + "name" : "villa", + "tags" : [ "architecture", "beach", "estate", "home", "house", "maps", "place", "real", "residence", "residential", "traveling", "vacation stay", "villa" ] +}, { + "name" : "fmd_bad", + "tags" : [ "!", "alert", "attention", "bad", "caution", "danger", "destination", "direction", "error", "exclamation", "fmd", "important", "location", "maps", "mark", "notification", "pin", "place", "symbol", "warning" ] +}, { + "name" : "flashlight_on", + "tags" : [ "disabled", "enabled", "flash", "flashlight", "light", "off", "on", "slash" ] +}, { + "name" : "flip", + "tags" : [ "edit", "editing", "flip", "image", "orientation", "scan scanning" ] +}, { + "name" : "nightlife", + "tags" : [ "alcohol", "bar", "bottle", "club", "cocktail", "dance", "drink", "food", "glass", "liquor", "music", "nightlife", "note", "wine" ] +}, { + "name" : "present_to_all", + "tags" : [ "all", "arrow", "present", "presentation", "screen", "share", "site", "slides", "to", "web", "website" ] +}, { + "name" : "do_disturb", + "tags" : [ "cancel", "close", "denied", "deny", "disturb", "do", "remove", "silence", "stop" ] +}, { + "name" : "outbound", + "tags" : [ "arrow", "circle", "directional", "outbound", "right", "up" ] +}, { + "name" : "local_pharmacy", + "tags" : [ "911", "aid", "cross", "emergency", "first", "hospital", "local", "medicine", "pharmacy", "places" ] +}, { + "name" : "splitscreen", + "tags" : [ "column", "grid", "layout", "multitasking", "row", "screen", "split", "splitscreen", "two" ] +}, { + "name" : "waterfall_chart", + "tags" : [ "analytics", "bar", "chart", "data", "diagram", "graph", "infographic", "measure", "metrics", "statistics", "tracking", "waterfall" ] +}, { + "name" : "switch_left", + "tags" : [ "arrows", "directional", "left", "navigation", "switch", "toggle" ] +}, { + "name" : "domain_verification", + "tags" : [ "app", "application desktop", "approve", "check", "complete", "design", "domain", "done", "interface", "internet", "layout", "mark", "ok", "screen", "select", "site", "tick", "ui", "ux", "validate", "verification", "verified", "web", "website", "window", "www", "yes" ] +}, { + "name" : "fireplace", + "tags" : [ "chimney", "fire", "fireplace", "flame", "home", "house", "living", "pit", "place", "room", "warm", "winter" ] +}, { + "name" : "video_settings", + "tags" : [ "change", "details", "gear", "info", "information", "options", "play", "screen", "service", "setting", "settings", "video", "window" ] +}, { + "name" : "disabled_visible", + "tags" : [ "cancel", "close", "disabled", "exit", "eye", "no", "on", "quit", "remove", "reveal", "see", "show", "stop", "view", "visibility", "visible" ] +}, { + "name" : "network_wifi", + "tags" : [ "cell", "cellular", "data", "internet", "mobile", "network", "phone", "speed", "wifi", "wireless" ] +}, { + "name" : "quickreply", + "tags" : [ "bolt", "bubble", "chat", "comment", "communicate", "fast", "lightning", "message", "quick", "quickreply", "reply", "speech", "thunderbolt" ] +}, { + "name" : "swap_vertical_circle", + "tags" : [ "arrow", "arrows", "circle", "down", "swap", "up", "vertical" ] +}, { + "name" : "format_align_justify", + "tags" : [ "align", "alignment", "density", "doc", "edit", "editing", "editor", "extra", "format", "justify", "sheet", "small", "spreadsheet", "text", "type", "writing" ] +}, { + "name" : "settings_input_composite", + "tags" : [ "component", "composite", "connection", "connectivity", "input", "plug", "points", "settings" ] +}, { + "name" : "loupe", + "tags" : [ "+", "add", "details", "focus", "glass", "loupe", "magnifying", "new", "plus", "symbol" ] +}, { + "name" : "123", + "tags" : [ "1", "2", "3", "digit", "number", "symbol" ] +}, { + "name" : "network_check", + "tags" : [ "check", "connect", "connection", "internet", "meter", "network", "signal", "speed", "tick", "wifi", "wireless" ] +}, { + "name" : "sms_failed", + "tags" : [ "!", "alert", "attention", "bubbles", "caution", "chat", "communication", "conversation", "danger", "error", "exclamation", "failed", "feedback", "important", "mark", "message", "notification", "service", "sms", "speech", "symbol", "warning" ] +}, { + "name" : "cancel_schedule_send", + "tags" : [ "cancel", "email", "mail", "no", "quit", "remove", "schedule", "send", "share", "stop", "x" ] +}, { + "name" : "work_history", + "tags" : [ "back", "backwards", "bag", "baggage", "briefcase", "business", "case", "clock", "date", "history", "job", "pending", "recent", "schedule", "suitcase", "time", "updates", "work" ] +}, { + "name" : "electric_bolt", + "tags" : [ "bolt", "electric", "energy", "fast", "lightning", "nest", "thunderbolt" ] +}, { + "name" : "view_day", + "tags" : [ "cards", "carousel", "day", "design", "format", "grid", "layout", "view", "website" ] +}, { + "name" : "night_shelter", + "tags" : [ "architecture", "bed", "building", "estate", "homeless", "house", "night", "place", "real", "shelter", "sleep" ] +}, { + "name" : "monitor", + "tags" : [ "Android", "OS", "chrome", "device", "display", "hardware", "iOS", "mac", "monitor", "screen", "web", "window" ] +}, { + "name" : "clean_hands", + "tags" : [ "bacteria", "clean", "disinfect", "germs", "gesture", "hand", "hands", "sanitize", "sanitizer" ] +}, { + "name" : "mark_chat_read", + "tags" : [ "approve", "bubble", "chat", "check", "comment", "communicate", "complete", "done", "mark", "message", "ok", "read", "select", "sent", "speech", "tick", "verified", "yes" ] +}, { + "name" : "comment_bank", + "tags" : [ "archive", "bank", "bookmark", "bubble", "cchat", "comment", "communicate", "favorite", "label", "library", "message", "remember", "ribbon", "save", "speech", "tag" ] +}, { + "name" : "sim_card_download", + "tags" : [ "arrow", "camera", "card", "chip", "device", "down", "download", "memory", "phone", "sim", "storage" ] +}, { + "name" : "lan", + "tags" : [ "computer", "connection", "data", "internet", "lan", "network", "service" ] +}, { + "name" : "piano", + "tags" : [ "instrument", "keyboard", "keys", "music", "musical", "piano", "social" ] +}, { + "name" : "add_road", + "tags" : [ "+", "add", "destination", "direction", "highway", "maps", "new", "plus", "road", "stop", "street", "symbol", "traffic" ] +}, { + "name" : "add_ic_call", + "tags" : [ "+", "add", "call", "cell", "contact", "device", "hardware", "mobile", "new", "phone", "plus", "symbol", "telephone" ] +}, { + "name" : "rule_folder", + "tags" : [ "approve", "cancel", "check", "close", "complete", "data", "doc", "document", "done", "drive", "exit", "file", "folder", "mark", "no", "ok", "remove", "rule", "select", "sheet", "slide", "storage", "tick", "validate", "verified", "x", "yes" ] +}, { + "name" : "switch_access_shortcut", + "tags" : [ "access", "arrow", "arrows", "direction", "navigation", "new", "north", "shortcut", "switch", "symbol", "up" ] +}, { + "name" : "hardware", + "tags" : [ "break", "construction", "hammer", "hardware", "nail", "repair", "tool" ] +}, { + "name" : "line_weight", + "tags" : [ "height", "line", "size", "spacing", "style", "thickness", "weight" ] +}, { + "name" : "image_not_supported", + "tags" : [ "disabled", "enabled", "image", "landscape", "mountain", "mountains", "not", "off", "on", "photo", "photography", "picture", "slash", "supported" ] +}, { + "name" : "flip_camera_ios", + "tags" : [ "DISABLE_IOS", "android", "camera", "disable_ios", "edit", "editing", "flip", "image", "ios", "mobile", "orientation", "rotate", "turn" ] +}, { + "name" : "phone_callback", + "tags" : [ "arrow", "call", "callback", "cell", "contact", "device", "down", "hardware", "mobile", "phone", "telephone" ] +}, { + "name" : "access_time_filled", + "tags" : [ ] +}, { + "name" : "dining", + "tags" : [ "cafe", "cafeteria", "cutlery", "diner", "dining", "eat", "eating", "fork", "room", "spoon" ] +}, { + "name" : "scale", + "tags" : [ "measure", "monitor", "scale", "weight" ] +}, { + "name" : "airplanemode_active", + "tags" : [ "active", "airplane", "airplanemode", "flight", "mode", "on", "signal" ] +}, { + "name" : "set_meal", + "tags" : [ "chopsticks", "dinner", "fish", "food", "lunch", "meal", "restaurant", "set", "teishoku" ] +}, { + "name" : "mobile_friendly", + "tags" : [ "Android", "OS", "approve", "cell", "check", "complete", "device", "done", "friendly", "hardware", "iOS", "mark", "mobile", "ok", "phone", "select", "tablet", "tick", "validate", "verified", "yes" ] +}, { + "name" : "assured_workload", + "tags" : [ "assured", "compliance", "confidential", "federal", "government", "secure", "sensitive regulatory", "workload" ] +}, { + "name" : "wallet", + "tags" : [ ] +}, { + "name" : "merge_type", + "tags" : [ "arrow", "combine", "direction", "format", "merge", "text", "type" ] +}, { + "name" : "view_timeline", + "tags" : [ "grid", "layout", "pattern", "squares", "timeline", "view" ] +}, { + "name" : "departure_board", + "tags" : [ "automobile", "board", "bus", "car", "cars", "clock", "departure", "maps", "public", "schedule", "time", "transportation", "travel", "vehicle" ] +}, { + "name" : "event_repeat", + "tags" : [ "around", "calendar", "date", "day", "event", "inprogress", "load", "loading refresh", "month", "renew", "rotate", "schedule", "turn" ] +}, { + "name" : "sanitizer", + "tags" : [ "bacteria", "bottle", "clean", "covid", "disinfect", "germs", "pump", "sanitizer" ] +}, { + "name" : "surfing", + "tags" : [ "athlete", "athletic", "beach", "body", "entertainment", "exercise", "hobby", "human", "people", "person", "sea", "social sports", "sports", "summer", "surfing", "water" ] +}, { + "name" : "pix", + "tags" : [ "bill", "brazil", "card", "cash", "commerce", "credit", "currency", "finance", "money", "payment" ] +}, { + "name" : "phonelink_ring", + "tags" : [ "Android", "OS", "cell", "connection", "data", "device", "hardware", "iOS", "mobile", "network", "phone", "phonelink", "ring", "service", "signal", "tablet", "wireless" ] +}, { + "name" : "display_settings", + "tags" : [ "Android", "OS", "application", "change", "chrome", "desktop", "details", "device", "display", "gear", "hardware", "iOS", "info", "information", "mac", "monitor", "options", "personal", "screen", "service", "settings", "web", "window" ] +}, { + "name" : "sports_motorsports", + "tags" : [ "athlete", "athletic", "automobile", "bike", "drive", "driving", "entertainment", "helmet", "hobby", "motorcycle", "motorsports", "protect", "social", "sports", "vehicle" ] +}, { + "name" : "horizontal_split", + "tags" : [ "bars", "format", "horizontal", "layout", "lines", "split", "stacked" ] +}, { + "name" : "view_comfy", + "tags" : [ "comfy", "grid", "layout", "pattern", "squares", "view" ] +}, { + "name" : "polymer", + "tags" : [ "emblem", "logo", "mark", "polymer" ] +}, { + "name" : "golf_course", + "tags" : [ "athlete", "athletic", "ball", "club", "course", "entertainment", "flag", "golf", "golfer", "golfing", "hobby", "hole", "places", "putt", "sports" ] +}, { + "name" : "batch_prediction", + "tags" : [ "batch", "bulb", "idea", "light", "prediction" ] +}, { + "name" : "filter_1", + "tags" : [ "1", "digit", "edit", "editing", "effect", "filter", "image", "images", "multiple", "number", "photography", "picture", "pictures", "settings", "stack", "symbol" ] +}, { + "name" : "stay_current_portrait", + "tags" : [ "Android", "OS", "current", "device", "hardware", "iOS", "mobile", "phone", "portrait", "stay", "tablet" ] +}, { + "name" : "usb", + "tags" : [ "cable", "connection", "device", "usb", "wire" ] +}, { + "name" : "featured_play_list", + "tags" : [ "collection", "featured", "highlighted", "list", "music", "play", "playlist", "recommended" ] +}, { + "name" : "data_object", + "tags" : [ "brackets", "code", "coder", "data", "object", "parentheses" ] +}, { + "name" : "co_present", + "tags" : [ "arrow", "co-present", "presentation", "screen", "share", "site", "slides", "togather", "web", "website" ] +}, { + "name" : "ev_station", + "tags" : [ "automobile", "car", "cars", "charging", "electric", "electricity", "ev", "maps", "places", "station", "transportation", "vehicle" ] +}, { + "name" : "send_and_archive", + "tags" : [ "archive", "arrow", "down", "download", "email", "letter", "mail", "save", "send", "share" ] +}, { + "name" : "send_to_mobile", + "tags" : [ "Android", "OS", "arrow", "device", "export", "forward", "hardware", "iOS", "mobile", "phone", "right", "send", "share", "tablet", "to" ] +}, { + "name" : "local_see", + "tags" : [ "camera", "lens", "local", "photo", "photography", "picture", "see" ] +}, { + "name" : "satellite_alt", + "tags" : [ "alternative", "artificial", "communication", "satellite", "space", "space station", "television" ] +}, { + "name" : "flatware", + "tags" : [ "cafe", "cafeteria", "cutlery", "diner", "dining", "eat", "eating", "fork", "room", "spoon" ] +}, { + "name" : "speaker", + "tags" : [ "box", "electronic", "loud", "music", "sound", "speaker", "stereo", "system", "video" ] +}, { + "name" : "adb", + "tags" : [ "adb", "android", "bridge", "debug" ] +}, { + "name" : "movie_creation", + "tags" : [ "cinema", "clapperboard", "creation", "film", "movie", "movies", "slate", "video" ] +}, { + "name" : "picture_in_picture", + "tags" : [ "crop", "cropped", "overlap", "photo", "picture", "position", "shape" ] +}, { + "name" : "call_received", + "tags" : [ "arrow", "call", "device", "mobile", "received" ] +}, { + "name" : "battery_alert", + "tags" : [ "!", "alert", "attention", "battery", "caution", "cell", "charge", "danger", "error", "exclamation", "important", "mark", "mobile", "notification", "power", "symbol", "warning" ] +}, { + "name" : "system_update", + "tags" : [ "Android", "OS", "arrow", "arrows", "cell", "device", "direction", "down", "download", "hardware", "iOS", "install", "mobile", "phone", "system", "tablet", "update" ] +}, { + "name" : "webhook", + "tags" : [ "api", "developer", "development", "enterprise", "software", "webhook" ] +}, { + "name" : "add_chart", + "tags" : [ "+", "add", "analytics", "bar", "bars", "chart", "data", "diagram", "graph", "infographic", "measure", "metrics", "new", "plus", "statistics", "symbol", "tracking" ] +}, { + "name" : "pan_tool_alt", + "tags" : [ "fingers", "gesture", "hand", "hands", "human", "move", "pan", "scan", "stop", "tool" ] +}, { + "name" : "sports_handball", + "tags" : [ "athlete", "athletic", "ball", "body", "entertainment", "exercise", "game", "handball", "hobby", "human", "people", "person", "social", "sports" ] +}, { + "name" : "electric_car", + "tags" : [ "automobile", "car", "cars", "electric", "electricity", "maps", "transportation", "travel", "vehicle" ] +}, { + "name" : "phone_forwarded", + "tags" : [ "arrow", "call", "cell", "contact", "device", "direction", "forwarded", "hardware", "mobile", "phone", "right", "telephone" ] +}, { + "name" : "add_to_photos", + "tags" : [ "add", "collection", "image", "landscape", "mountain", "mountains", "photo", "photography", "photos", "picture", "plus", "to" ] +}, { + "name" : "power_off", + "tags" : [ "charge", "cord", "disabled", "electric", "electrical", "enabled", "off", "on", "outlet", "plug", "power", "slash" ] +}, { + "name" : "noise_control_off", + "tags" : [ "audio", "aware", "cancel", "cancellation", "control", "disabled", "enabled", "music", "noise", "note", "off", "offline", "on", "slash", "sound" ] +}, { + "name" : "code_off", + "tags" : [ "brackets", "code", "css", "develop", "developer", "disabled", "enabled", "engineer", "engineering", "html", "off", "on", "platform", "slash" ] +}, { + "name" : "bookmark_remove", + "tags" : [ "bookmark", "delete", "favorite", "minus", "remember", "remove", "ribbon", "save", "subtract" ] +}, { + "name" : "screen_search_desktop", + "tags" : [ "Android", "OS", "arrow", "desktop", "device", "hardware", "iOS", "lock", "monitor", "rotate", "screen", "web" ] +}, { + "name" : "panorama", + "tags" : [ "angle", "image", "mountain", "mountains", "panorama", "photo", "photography", "picture", "view", "wide" ] +}, { + "name" : "settings_bluetooth", + "tags" : [ "bluetooth", "connect", "connection", "connectivity", "device", "settings", "signal", "symbol" ] +}, { + "name" : "sports_baseball", + "tags" : [ "athlete", "athletic", "ball", "baseball", "entertainment", "exercise", "game", "hobby", "social", "sports" ] +}, { + "name" : "festival", + "tags" : [ "circus", "event", "festival", "local", "maps", "places", "tent", "tour", "travel" ] +}, { + "name" : "lens_blur", + "tags" : [ "blur", "camera", "dim", "dot", "effect", "foggy", "fuzzy", "image", "lens", "photo", "soften" ] +}, { + "name" : "plumbing", + "tags" : [ "build", "construction", "fix", "handyman", "plumbing", "repair", "tools", "wrench" ] +}, { + "name" : "toys", + "tags" : [ "car", "games", "kids", "toy", "toys", "windmill" ] +}, { + "name" : "coffee_maker", + "tags" : [ "appliances", "beverage", "coffee", "cup", "drink", "machine", "maker", "mug" ] +}, { + "name" : "edit_notifications", + "tags" : [ "active", "alarm", "alert", "bell", "chime", "compose", "create", "draft", "edit", "editing", "input", "new", "notifications", "notify", "pen", "pencil", "reminder", "ring", "sound", "write", "writing" ] +}, { + "name" : "personal_video", + "tags" : [ "Android", "OS", "cam", "chrome", "desktop", "device", "hardware", "iOS", "mac", "monitor", "personal", "television", "tv", "video", "web", "window" ] +}, { + "name" : "animation", + "tags" : [ "animation", "circles", "film", "motion", "movement", "sequence", "video" ] +}, { + "name" : "bedtime", + "tags" : [ "bedtime", "nightime", "sleep" ] +}, { + "name" : "gamepad", + "tags" : [ "buttons", "console", "controller", "device", "game", "gamepad", "gaming", "playstation", "video" ] +}, { + "name" : "diversity_1", + "tags" : [ "committee", "diverse", "diversity", "family", "friends", "group", "groups", "heart", "humans", "network", "people", "persons", "social", "team" ] +}, { + "name" : "center_focus_weak", + "tags" : [ "camera", "center", "focus", "image", "lens", "photo", "photography", "weak", "zoom" ] +}, { + "name" : "signal_wifi_statusbar_4_bar", + "tags" : [ "4", "bar", "cell", "cellular", "data", "internet", "mobile", "network", "phone", "signal", "speed", "statusbar", "wifi", "wireless" ] +}, { + "name" : "manage_history", + "tags" : [ "application", "arrow", "back", "backwards", "change", "clock", "date", "details", "gear", "history", "options", "refresh", "renew", "reverse", "rotate", "schedule", "settings", "time", "turn" ] +}, { + "name" : "folder_zip", + "tags" : [ "compress", "data", "doc", "document", "drive", "file", "folder", "folders", "open", "sheet", "slide", "storage", "zip" ] +}, { + "name" : "flag_circle", + "tags" : [ "circle", "country", "flag", "goal", "mark", "nation", "report", "round", "start" ] +}, { + "name" : "south_west", + "tags" : [ "arrow", "directional", "down", "left", "maps", "navigation", "south", "west" ] +}, { + "name" : "looks_4", + "tags" : [ "4", "digit", "looks", "numbers", "square", "symbol" ] +}, { + "name" : "cloud_circle", + "tags" : [ "app", "application", "backup", "circle", "cloud", "connection", "drive", "files", "folders", "internet", "network", "sky", "storage", "upload" ] +}, { + "name" : "format_shapes", + "tags" : [ "alphabet", "character", "color", "doc", "edit", "editing", "editor", "fill", "font", "format", "letter", "paint", "shapes", "sheet", "spreadsheet", "style", "symbol", "text", "type", "writing" ] +}, { + "name" : "car_rental", + "tags" : [ "automobile", "car", "cars", "key", "maps", "rental", "transportation", "vehicle" ] +}, { + "name" : "movie_filter", + "tags" : [ "ai", "artificial", "automatic", "automation", "clapperboard", "creation", "custom", "film", "filter", "genai", "intelligence", "magic", "movie", "movies", "slate", "smart", "spark", "sparkle", "star", "stars", "video" ] +}, { + "name" : "layers_clear", + "tags" : [ "arrange", "clear", "delete", "disabled", "enabled", "interaction", "layers", "maps", "off", "on", "overlay", "pages", "slash" ] +}, { + "name" : "phonelink_lock", + "tags" : [ "Android", "OS", "cell", "connection", "device", "erase", "hardware", "iOS", "lock", "locked", "mobile", "password", "phone", "phonelink", "privacy", "private", "protection", "safety", "secure", "security", "tablet" ] +}, { + "name" : "attractions", + "tags" : [ "amusement", "attractions", "entertainment", "ferris", "fun", "maps", "park", "places", "wheel" ] +}, { + "name" : "playlist_add_check_circle", + "tags" : [ "add", "album", "artist", "audio", "cd", "check", "circle", "collection", "list", "mark", "music", "playlist", "record", "sound", "track" ] +}, { + "name" : "hive", + "tags" : [ "bee", "honey", "honeycomb" ] +}, { + "name" : "no_photography", + "tags" : [ "camera", "disabled", "enabled", "image", "no", "off", "on", "photo", "photography", "picture", "slash" ] +}, { + "name" : "content_paste_go", + "tags" : [ "clipboard", "content", "disabled", "doc", "document", "enabled", "file", "go", "on", "paste", "slash" ] +}, { + "name" : "shop_two", + "tags" : [ "add", "arrow", "buy", "cart", "google", "play", "purchase", "shop", "shopping", "two" ] +}, { + "name" : "edit_location", + "tags" : [ "destination", "direction", "edit", "location", "maps", "pen", "pencil", "pin", "place", "stop" ] +}, { + "name" : "screen_rotation", + "tags" : [ "Android", "OS", "arrow", "device", "hardware", "iOS", "mobile", "phone", "rotate", "rotation", "screen", "tablet", "turn" ] +}, { + "name" : "numbers", + "tags" : [ "digit", "number", "numbers", "symbol" ] +}, { + "name" : "sim_card", + "tags" : [ "camera", "card", "chip", "device", "memory", "phone", "sim", "storage" ] +}, { + "name" : "control_camera", + "tags" : [ "adjust", "arrow", "arrows", "camera", "center", "control", "direction", "left", "move", "right" ] +}, { + "name" : "blender", + "tags" : [ "appliance", "blender", "cooking", "electric", "juicer", "kitchen", "machine", "vitamix" ] +}, { + "name" : "flip_to_front", + "tags" : [ "arrange", "arrangement", "back", "flip", "format", "front", "layout", "move", "order", "sort", "to" ] +}, { + "name" : "sports_volleyball", + "tags" : [ "athlete", "athletic", "ball", "entertainment", "exercise", "game", "hobby", "social", "sports", "volleyball" ] +}, { + "name" : "stairs", + "tags" : [ "down", "staircase", "stairs", "up" ] +}, { + "name" : "keyboard_alt", + "tags" : [ "alt", "computer", "device", "hardware", "input", "keyboard", "keypad", "letter", "office", "text", "type" ] +}, { + "name" : "crop_din", + "tags" : [ "adjust", "adjustments", "area", "crop", "din", "edit", "editing", "frame", "image", "images", "photo", "photos", "rectangle", "settings", "size", "square" ] +}, { + "name" : "html", + "tags" : [ "alphabet", "brackets", "character", "code", "css", "develop", "developer", "engineer", "engineering", "font", "html", "letter", "platform", "symbol", "text", "type" ] +}, { + "name" : "signal_wifi_statusbar_connected_no_internet_4", + "tags" : [ "!", "4", "alert", "attention", "caution", "cell", "cellular", "connected", "danger", "data", "error", "exclamation", "important", "internet", "mark", "mobile", "network", "no", "notification", "phone", "signal", "speed", "statusbar", "symbol", "warning", "wifi", "wireless" ] +}, { + "name" : "pivot_table_chart", + "tags" : [ "analytics", "arrow", "arrows", "bar", "bars", "chart", "data", "diagram", "direction", "drive", "edit", "editing", "graph", "grid", "infographic", "measure", "metrics", "pivot", "rotate", "sheet", "statistics", "table", "tracking" ] +}, { + "name" : "microwave", + "tags" : [ "appliance", "cooking", "electric", "heat", "home", "house", "kitchen", "machine", "microwave" ] +}, { + "name" : "folder_copy", + "tags" : [ "content", "copy", "cut", "data", "doc", "document", "drive", "duplicate", "file", "folder", "folders", "multiple", "paste", "sheet", "slide", "storage" ] +}, { + "name" : "output", + "tags" : [ ] +}, { + "name" : "gif_box", + "tags" : [ "alphabet", "animated", "animation", "bitmap", "character", "font", "format", "gif", "graphics", "interchange", "letter", "symbol", "text", "type" ] +}, { + "name" : "voice_chat", + "tags" : [ "bubble", "cam", "camera", "chat", "comment", "communicate", "facetime", "feedback", "message", "speech", "video", "voice" ] +}, { + "name" : "local_convenience_store", + "tags" : [ "--", "24", "bill", "building", "business", "card", "cash", "coin", "commerce", "company", "convenience", "credit", "currency", "dollars", "local", "maps", "market", "money", "new", "online", "pay", "payment", "plus", "shop", "shopping", "store", "storefront", "symbol" ] +}, { + "name" : "gps_not_fixed", + "tags" : [ "destination", "direction", "disabled", "enabled", "gps", "location", "maps", "not fixed", "off", "on", "online", "place", "pointer", "slash", "tracking" ] +}, { + "name" : "high_quality", + "tags" : [ "alphabet", "character", "definition", "display", "font", "high", "hq", "letter", "movie", "movies", "quality", "resolution", "screen", "symbol", "text", "tv", "type" ] +}, { + "name" : "switch_right", + "tags" : [ "arrows", "directional", "navigation", "right", "switch", "toggle" ] +}, { + "name" : "pages", + "tags" : [ "article", "gplus", "pages", "paper", "post", "star" ] +}, { + "name" : "table_restaurant", + "tags" : [ "bar", "dining", "table" ] +}, { + "name" : "speaker_notes_off", + "tags" : [ "bubble", "chat", "comment", "communicate", "disabled", "enabled", "format", "list", "message", "notes", "off", "on", "slash", "speaker", "speech", "text" ] +}, { + "name" : "phone_disabled", + "tags" : [ "call", "cell", "contact", "device", "disabled", "enabled", "hardware", "mobile", "off", "offline", "on", "phone", "slash", "telephone" ] +}, { + "name" : "eject", + "tags" : [ "disc", "drive", "dvd", "eject", "remove", "triangle", "usb" ] +}, { + "name" : "control_point_duplicate", + "tags" : [ "+", "add", "circle", "control", "duplicate", "multiple", "new", "plus", "point", "symbol" ] +}, { + "name" : "filter", + "tags" : [ "edit", "editing", "effect", "filter", "image", "landscape", "mountain", "mountains", "photo", "photography", "picture", "settings" ] +}, { + "name" : "pest_control", + "tags" : [ "bug", "control", "exterminator", "insects", "pest" ] +}, { + "name" : "backpack", + "tags" : [ "back", "backpack", "bag", "book", "bookbag", "knapsack", "pack", "storage", "travel" ] +}, { + "name" : "leak_add", + "tags" : [ "add", "connection", "data", "leak", "link", "network", "service", "signals", "synce", "wireless" ] +}, { + "name" : "zoom_in_map", + "tags" : [ "arrow", "arrows", "destination", "in", "location", "maps", "move", "place", "stop", "zoom" ] +}, { + "name" : "brightness_7", + "tags" : [ "7", "brightness", "circle", "control", "crescent", "level", "moon", "screen", "sun" ] +}, { + "name" : "system_security_update_good", + "tags" : [ "Android", "OS", "approve", "cell", "check", "complete", "device", "done", "good", "hardware", "iOS", "mark", "mobile", "ok", "phone", "security", "select", "system", "tablet", "tick", "update", "validate", "verified", "yes" ] +}, { + "name" : "ring_volume", + "tags" : [ "call", "calling", "cell", "contact", "device", "hardware", "incoming", "mobile", "phone", "ring", "ringer", "sound", "telephone", "volume" ] +}, { + "name" : "money_off_csred", + "tags" : [ "bill", "card", "cart", "cash", "coin", "commerce", "credit", "csred", "currency", "disabled", "dollars", "enabled", "money", "off", "on", "online", "pay", "payment", "shopping", "slash", "symbol" ] +}, { + "name" : "sports_football", + "tags" : [ "athlete", "athletic", "ball", "entertainment", "exercise", "football", "game", "hobby", "social", "sports" ] +}, { + "name" : "nature", + "tags" : [ "forest", "nature", "outdoor", "outside", "park", "tree", "wilderness" ] +}, { + "name" : "vibration", + "tags" : [ "Android", "OS", "alert", "cell", "device", "hardware", "iOS", "mobile", "mode", "motion", "notification", "phone", "silence", "silent", "tablet", "vibrate", "vibration" ] +}, { + "name" : "snippet_folder", + "tags" : [ "data", "doc", "document", "drive", "file", "folder", "sheet", "slide", "snippet", "storage" ] +}, { + "name" : "edit_road", + "tags" : [ "destination", "direction", "edit", "highway", "maps", "pen", "pencil", "road", "street", "traffic" ] +}, { + "name" : "run_circle", + "tags" : [ "body", "circle", "exercise", "human", "people", "person", "run", "running" ] +}, { + "name" : "dry_cleaning", + "tags" : [ "cleaning", "dry", "hanger", "hotel", "laundry", "places", "service", "towel" ] +}, { + "name" : "alarm_off", + "tags" : [ "alarm", "alert", "bell", "clock", "disabled", "duration", "enabled", "notification", "off", "on", "slash", "time", "timer", "watch" ] +}, { + "name" : "perm_data_setting", + "tags" : [ "data", "gear", "info", "information", "perm", "settings" ] +}, { + "name" : "bedroom_parent", + "tags" : [ "bed", "bedroom", "double", "full", "furniture", "home", "hotel", "house", "king", "night", "parent", "pillows", "queen", "rest", "room", "sizem master", "sleep" ] +}, { + "name" : "airline_seat_recline_normal", + "tags" : [ "airline", "body", "extra", "feet", "human", "leg", "legroom", "normal", "people", "person", "recline", "seat", "sitting", "space", "travel" ] +}, { + "name" : "currency_bitcoin", + "tags" : [ "bill", "blockchain", "card", "cash", "coin", "commerce", "cost", "credit", "currency", "digital", "dollars", "finance", "franc", "money", "online", "pay", "payment", "price", "shopping", "symbol" ] +}, { + "name" : "do_disturb_alt", + "tags" : [ "cancel", "close", "denied", "deny", "disturb", "do", "remove", "silence", "stop" ] +}, { + "name" : "sensor_window", + "tags" : [ "alarm", "security", "security system" ] +}, { + "name" : "incomplete_circle", + "tags" : [ "chart", "circle", "incomplete" ] +}, { + "name" : "settings_input_hdmi", + "tags" : [ "cable", "connection", "connectivity", "definition", "hdmi", "high", "input", "plug", "plugin", "points", "settings", "video", "wire" ] +}, { + "name" : "camera_indoor", + "tags" : [ "architecture", "building", "camera", "estate", "film", "filming", "home", "house", "image", "indoor", "inside", "motion", "nest", "picture", "place", "real", "residence", "residential", "shelter", "video", "videography" ] +}, { + "name" : "edit_location_alt", + "tags" : [ "alt", "edit", "location", "pen", "pencil", "pin" ] +}, { + "name" : "texture", + "tags" : [ "diagonal", "lines", "pattern", "stripes", "texture" ] +}, { + "name" : "location_off", + "tags" : [ "destination", "direction", "location", "maps", "off", "pin", "place", "room", "stop" ] +}, { + "name" : "edit_attributes", + "tags" : [ "approve", "attribution", "check", "complete", "done", "edit", "mark", "ok", "select", "tick", "validate", "verified", "yes" ] +}, { + "name" : "duo", + "tags" : [ "call", "chat", "conference", "device", "duo", "video" ] +}, { + "name" : "slow_motion_video", + "tags" : [ "arrow", "control", "controls", "motion", "music", "play", "slow", "speed", "video" ] +}, { + "name" : "perm_scan_wifi", + "tags" : [ "alert", "announcement", "connection", "info", "information", "internet", "network", "perm", "scan", "service", "signal", "wifi", "wireless" ] +}, { + "name" : "phonelink_setup", + "tags" : [ "Android", "OS", "call", "chat", "device", "hardware", "iOS", "info", "mobile", "phone", "phonelink", "settings", "setup", "tablet", "text" ] +}, { + "name" : "hourglass_disabled", + "tags" : [ "clock", "countdown", "disabled", "empty", "enabled", "hourglass", "loading", "minute", "minutes", "off", "on", "slash", "time", "wait", "waiting" ] +}, { + "name" : "add_to_queue", + "tags" : [ "+", "Android", "OS", "add", "chrome", "desktop", "device", "display", "hardware", "iOS", "mac", "monitor", "new", "plus", "queue", "screen", "symbol", "to", "web", "window" ] +}, { + "name" : "pie_chart_outline", + "tags" : [ "analytics", "bar", "bars", "chart", "data", "diagram", "graph", "infographic", "measure", "metrics", "outline", "pie", "statistics", "tracking" ] +}, { + "name" : "playlist_remove", + "tags" : [ "-", "collection", "list", "minus", "music", "playlist", "remove" ] +}, { + "name" : "next_week", + "tags" : [ "arrow", "bag", "baggage", "briefcase", "business", "case", "next", "suitcase", "week" ] +}, { + "name" : "church", + "tags" : [ "christian", "christianity", "religion", "spiritual", "worship" ] +}, { + "name" : "medical_information", + "tags" : [ "badge", "card", "health", "id", "information", "medical", "services" ] +}, { + "name" : "view_compact", + "tags" : [ "compact", "grid", "layout", "pattern", "squares", "view" ] +}, { + "name" : "timer_off", + "tags" : [ "alarm", "alert", "bell", "clock", "disabled", "duration", "enabled", "notification", "off", "on", "slash", "stop", "time", "timer", "watch" ] +}, { + "name" : "bluetooth_connected", + "tags" : [ "bluetooth", "cast", "connect", "connection", "device", "paring", "streaming", "symbol", "wireless" ] +}, { + "name" : "photo_size_select_actual", + "tags" : [ "actual", "image", "mountain", "mountains", "photo", "photography", "picture", "select", "size" ] +}, { + "name" : "short_text", + "tags" : [ "brief", "comment", "doc", "document", "note", "short", "text", "write", "writing" ] +}, { + "name" : "bedroom_baby", + "tags" : [ "babies", "baby", "bedroom", "child", "children", "home", "horse", "house", "infant", "kid", "newborn", "rocking", "room", "toddler", "young" ] +}, { + "name" : "video_camera_back", + "tags" : [ "back", "camera", "image", "landscape", "mountain", "mountains", "photo", "photography", "picture", "rear", "video" ] +}, { + "name" : "bathroom", + "tags" : [ "bath", "bathroom", "closet", "home", "house", "place", "plumbing", "room", "shower", "sprinkler", "wash", "water", "wc" ] +}, { + "name" : "downhill_skiing", + "tags" : [ "athlete", "athletic", "body", "downhill", "entertainment", "exercise", "hobby", "human", "people", "person", "ski social", "skiing", "snow", "sports", "travel", "winter" ] +}, { + "name" : "filter_list_off", + "tags" : [ "alt", "disabled", "edit", "filter", "list", "off", "offline", "options", "refine", "sift", "slash" ] +}, { + "name" : "connected_tv", + "tags" : [ "Android", "OS", "airplay", "chrome", "connect", "connected", "desktop", "device", "display", "hardware", "iOS", "mac", "monitor", "screen", "screencast", "streaming", "television", "tv", "web", "window", "wireless" ] +}, { + "name" : "format_indent_increase", + "tags" : [ "align", "alignment", "doc", "edit", "editing", "editor", "format", "increase", "indent", "indentation", "paragraph", "sheet", "spreadsheet", "text", "type", "writing" ] +}, { + "name" : "settings_cell", + "tags" : [ "Android", "OS", "cell", "device", "hardware", "iOS", "mobile", "phone", "settings", "tablet" ] +}, { + "name" : "remember_me", + "tags" : [ "Android", "OS", "avatar", "device", "hardware", "human", "iOS", "identity", "me", "mobile", "people", "person", "phone", "profile", "remember", "tablet", "user" ] +}, { + "name" : "kayaking", + "tags" : [ "athlete", "athletic", "body", "canoe", "entertainment", "exercise", "hobby", "human", "kayak", "kayaking", "lake", "paddle", "paddling", "people", "person", "rafting", "river", "row", "social", "sports", "summer", "travel", "water" ] +}, { + "name" : "switch_access_shortcut_add", + "tags" : [ "+", "access", "add", "arrow", "arrows", "direction", "navigation", "new", "north", "plus", "shortcut", "switch", "symbol", "up" ] +}, { + "name" : "app_blocking", + "tags" : [ "Android", "OS", "app", "application", "block", "blocking", "cancel", "cell", "device", "hardware", "iOS", "mobile", "phone", "stop", "stopped", "tablet" ] +}, { + "name" : "elevator", + "tags" : [ "body", "down", "elevator", "human", "people", "person", "up" ] +}, { + "name" : "work_off", + "tags" : [ "bag", "baggage", "briefcase", "business", "case", "disabled", "enabled", "job", "off", "on", "slash", "suitcase", "work" ] +}, { + "name" : "sensors_off", + "tags" : [ "connection", "disabled", "enabled", "network", "off", "on", "scan", "sensors", "signal", "slash", "wireless" ] +}, { + "name" : "stay_primary_portrait", + "tags" : [ "Android", "OS", "current", "device", "hardware", "iOS", "mobile", "phone", "portrait", "primary", "stay", "tablet" ] +}, { + "name" : "cell_tower", + "tags" : [ "broadcast", "casting", "cell", "network", "signal", "tower", "transmitting", "wireless" ] +}, { + "name" : "moped", + "tags" : [ "automobile", "bike", "car", "cars", "maps", "scooter", "transportation", "vehicle", "vespa" ] +}, { + "name" : "wrong_location", + "tags" : [ "cancel", "close", "destination", "direction", "exit", "location", "maps", "no", "pin", "place", "quit", "remove", "stop", "wrong", "x" ] +}, { + "name" : "groups_2", + "tags" : [ "body", "club", "collaboration", "crowd", "gathering", "groups", "hair", "human", "meeting", "people", "person", "social", "teams" ] +}, { + "name" : "public_off", + "tags" : [ "disabled", "earth", "enabled", "global", "globe", "map", "network", "off", "on", "planet", "public", "slash", "social", "space", "web", "world" ] +}, { + "name" : "picture_in_picture_alt", + "tags" : [ "crop", "cropped", "overlap", "photo", "picture", "position", "shape" ] +}, { + "name" : "chair_alt", + "tags" : [ "cahir", "furniture", "home", "house", "kitchen", "lounging", "seating", "table" ] +}, { + "name" : "car_repair", + "tags" : [ "automobile", "car", "cars", "maps", "repair", "transportation", "vehicle" ] +}, { + "name" : "airplay", + "tags" : [ "airplay", "arrow", "connect", "control", "desktop", "device", "display", "monitor", "screen", "signal" ] +}, { + "name" : "nfc", + "tags" : [ "communication", "data", "field", "mobile", "near", "nfc", "wireless" ] +}, { + "name" : "line_style", + "tags" : [ "dash", "dotted", "line", "rule", "spacing", "style" ] +}, { + "name" : "transform", + "tags" : [ "adjust", "crop", "edit", "editing", "image", "photo", "picture", "transform" ] +}, { + "name" : "single_bed", + "tags" : [ "bed", "bedroom", "double", "furniture", "home", "hotel", "house", "king", "night", "pillows", "queen", "rest", "room", "single", "sleep", "twin" ] +}, { + "name" : "pattern", + "tags" : [ "key", "login", "password", "pattern", "pin", "security", "star", "unlock" ] +}, { + "name" : "local_movies", + "tags" : [ ] +}, { + "name" : "repeat_one", + "tags" : [ "1", "arrow", "arrows", "control", "controls", "digit", "media", "music", "number", "one", "repeat", "symbol", "video" ] +}, { + "name" : "swap_calls", + "tags" : [ "arrow", "arrows", "calls", "device", "direction", "mobile", "share", "swap" ] +}, { + "name" : "do_not_disturb_alt", + "tags" : [ "cancel", "close", "denied", "deny", "disturb", "do", "remove", "silence", "stop" ] +}, { + "name" : "smoking_rooms", + "tags" : [ "allowed", "cigarette", "places", "rooms", "smoke", "smoking", "tobacco", "zone" ] +}, { + "name" : "remove_moderator", + "tags" : [ "certified", "disabled", "enabled", "moderator", "off", "on", "privacy", "private", "protect", "protection", "remove", "security", "shield", "slash", "verified" ] +}, { + "name" : "perm_device_information", + "tags" : [ "Android", "OS", "alert", "announcement", "device", "hardware", "i", "iOS", "info", "information", "mobile", "perm", "phone", "tablet" ] +}, { + "name" : "wash", + "tags" : [ "bathroom", "clean", "fingers", "gesture", "hand", "wash", "wc" ] +}, { + "name" : "mode_standby", + "tags" : [ "disturb", "mode", "power", "sleep", "standby", "target" ] +}, { + "name" : "door_sliding", + "tags" : [ "auto", "automatic", "door", "doorway", "double", "entrance", "exit", "glass", "home", "house", "sliding", "two" ] +}, { + "name" : "skateboarding", + "tags" : [ "athlete", "athletic", "body", "entertainment", "exercise", "hobby", "human", "people", "person", "skate", "skateboarder", "skateboarding", "social", "sports" ] +}, { + "name" : "difference", + "tags" : [ "compare", "content", "copy", "cut", "diff", "difference", "doc", "document", "duplicate", "file", "multiple", "past" ] +}, { + "name" : "group_remove", + "tags" : [ "accounts", "committee", "face", "family", "friends", "group", "humans", "network", "people", "persons", "profiles", "remove", "social", "team", "users" ] +}, { + "name" : "brightness_high", + "tags" : [ "auto", "brightness", "control", "high", "mobile", "monitor", "phone", "sun" ] +}, { + "name" : "cabin", + "tags" : [ "architecture", "cabin", "camping", "cottage", "estate", "home", "house", "log", "maps", "place", "real", "residence", "residential", "stay", "traveling", "wood" ] +}, { + "name" : "camera_outdoor", + "tags" : [ "architecture", "building", "camera", "estate", "film", "filming", "home", "house", "image", "motion", "nest", "outdoor", "outside", "picture", "place", "real", "residence", "residential", "shelter", "video", "videography" ] +}, { + "name" : "troubleshoot", + "tags" : [ "analytics", "chart", "data", "diagram", "find", "glass", "graph", "infographic", "line", "look", "magnify", "magnifying", "measure", "metrics", "search", "see", "statistics", "tracking", "troubleshoot" ] +}, { + "name" : "tablet_android", + "tags" : [ "OS", "android", "device", "hardware", "iOS", "ipad", "mobile", "tablet", "web" ] +}, { + "name" : "house_siding", + "tags" : [ "architecture", "building", "construction", "estate", "exterior", "facade", "home", "house", "real", "residential", "siding" ] +}, { + "name" : "satellite", + "tags" : [ "bluetooth", "connect", "connection", "connectivity", "data", "device", "image", "internet", "landscape", "location", "maps", "mountain", "mountains", "network", "photo", "photography", "picture", "satellite", "scan", "service", "signal", "symbol", "wireless-- wifi" ] +}, { + "name" : "motion_photos_on", + "tags" : [ "animation", "circle", "disabled", "enabled", "motion", "off", "on", "photos", "play", "slash", "video" ] +}, { + "name" : "door_back", + "tags" : [ "back", "closed", "door", "doorway", "entrance", "exit", "home", "house", "way" ] +}, { + "name" : "strikethrough_s", + "tags" : [ "alphabet", "character", "cross", "doc", "edit", "editing", "editor", "font", "letter", "out", "s", "sheet", "spreadsheet", "strikethrough", "styles", "symbol", "text", "type", "writing" ] +}, { + "name" : "co2", + "tags" : [ "carbon", "chemical", "co2", "dioxide", "gas" ] +}, { + "name" : "notifications_paused", + "tags" : [ "active", "alarm", "alert", "bell", "chime", "ignore", "notifications", "notify", "paused", "quiet", "reminder", "ring --- pause", "sleep", "snooze", "sound", "z", "zzz" ] +}, { + "name" : "currency_yen", + "tags" : [ "bill", "card", "cash", "coin", "commerce", "cost", "credit", "currency", "dollars", "finance", "money", "online", "pay", "payment", "price", "shopping", "symbol", "yen" ] +}, { + "name" : "call_to_action", + "tags" : [ "action", "alert", "bar", "call", "components", "cta", "design", "info", "information", "interface", "layout", "message", "notification", "screen", "site", "to", "ui", "ux", "web", "website", "window" ] +}, { + "name" : "photo_camera_front", + "tags" : [ "account", "camera", "face", "front", "human", "image", "people", "person", "photo", "photography", "picture", "portrait", "profile", "user" ] +}, { + "name" : "directions_boat_filled", + "tags" : [ "automobile", "boat", "car", "cars", "direction", "directions", "ferry", "filled", "maps", "public", "transportation", "vehicle" ] +}, { + "name" : "subtitles_off", + "tags" : [ "accessibility", "accessible", "caption", "cc", "closed", "disabled", "enabled", "language", "off", "on", "slash", "subtitle", "subtitles", "translate", "video" ] +}, { + "name" : "rotate_90_degrees_ccw", + "tags" : [ "90", "arrow", "arrows", "ccw", "degrees", "direction", "edit", "editing", "image", "photo", "rotate", "turn" ] +}, { + "name" : "vertical_align_center", + "tags" : [ "align", "alignment", "arrow", "center", "doc", "down", "edit", "editing", "editor", "sheet", "spreadsheet", "text", "type", "up", "vertical", "writing" ] +}, { + "name" : "living", + "tags" : [ "chair", "comfort", "couch", "decoration", "furniture", "home", "house", "living", "lounging", "loveseat", "room", "seat", "seating", "sofa" ] +}, { + "name" : "battery_saver", + "tags" : [ "+", "add", "battery", "charge", "charging", "new", "plus", "power", "saver", "symbol" ] +}, { + "name" : "hot_tub", + "tags" : [ "bath", "bathing", "bathroom", "bathtub", "hot", "hotel", "human", "jacuzzi", "person", "shower", "spa", "steam", "travel", "tub", "water" ] +}, { + "name" : "play_lesson", + "tags" : [ "audio", "book", "bookmark", "digital", "ebook", "lesson", "multimedia", "play", "play lesson", "read", "reading", "ribbon" ] +}, { + "name" : "update_disabled", + "tags" : [ "arrow", "back", "backwards", "clock", "date", "disabled", "enabled", "forward", "history", "load", "off", "on", "refresh", "reverse", "rotate", "schedule", "slash", "time", "update" ] +}, { + "name" : "psychology_alt", + "tags" : [ "?", "assistance", "behavior", "body", "brain", "cognitive", "function", "gear", "head", "help", "human", "info", "information", "intellectual", "mental", "mind", "people", "person", "preferences", "psychiatric", "psychology", "punctuation", "question mark", "science", "settings", "social", "support", "symbol", "therapy", "thinking", "thoughts" ] +}, { + "name" : "cast_connected", + "tags" : [ "Android", "OS", "airplay", "cast", "chrome", "connect", "connected", "desktop", "device", "display", "hardware", "iOS", "mac", "monitor", "screen", "screencast", "streaming", "television", "tv", "web", "window", "wireless" ] +}, { + "name" : "format_color_reset", + "tags" : [ "clear", "color", "disabled", "doc", "droplet", "edit", "editing", "editor", "enabled", "fill", "format", "off", "on", "paint", "reset", "sheet", "slash", "spreadsheet", "style", "text", "type", "water", "writing" ] +}, { + "name" : "snooze", + "tags" : [ "alarm", "bell", "clock", "duration", "notification", "snooze", "time", "timer", "watch", "z" ] +}, { + "name" : "person_remove_alt_1", + "tags" : [ ] +}, { + "name" : "align_horizontal_left", + "tags" : [ "align", "alignment", "format", "horizontal", "layout", "left", "lines", "paragraph", "rule", "rules", "style", "text" ] +}, { + "name" : "boy", + "tags" : [ "body", "boy", "gender", "human", "male", "man", "people", "person", "social", "symbol" ] +}, { + "name" : "battery_5_bar", + "tags" : [ "5", "bar", "battery", "cell", "charge", "mobile", "power" ] +}, { + "name" : "mic_external_on", + "tags" : [ "audio", "disabled", "enabled", "external", "mic", "microphone", "off", "on", "slash", "sound", "voice" ] +}, { + "name" : "voicemail", + "tags" : [ "call", "device", "message", "missed", "mobile", "phone", "recording", "voice", "voicemail" ] +}, { + "name" : "join_full", + "tags" : [ "circle", "combine", "command", "full", "join", "left", "outer", "overlap", "right", "sql" ] +}, { + "name" : "looks_5", + "tags" : [ "5", "digit", "looks", "numbers", "square", "symbol" ] +}, { + "name" : "countertops", + "tags" : [ "counter", "countertops", "home", "house", "kitchen", "sink", "table", "tops" ] +}, { + "name" : "energy_savings_leaf", + "tags" : [ "eco", "energy", "leaf", "leaves", "nest", "savings", "usage" ] +}, { + "name" : "safety_divider", + "tags" : [ "apart", "distance", "divider", "safety", "separate", "social", "space" ] +}, { + "name" : "move_up", + "tags" : [ "arrow", "direction", "jump", "move", "navigation", "transfer", "up" ] +}, { + "name" : "storm", + "tags" : [ "forecast", "hurricane", "storm", "temperature", "twister", "weather", "wind" ] +}, { + "name" : "sync_disabled", + "tags" : [ "360", "around", "arrow", "arrows", "direction", "disabled", "enabled", "inprogress", "load", "loading refresh", "off", "on", "renew", "rotate", "slash", "sync", "turn" ] +}, { + "name" : "javascript", + "tags" : [ "alphabet", "brackets", "character", "code", "css", "develop", "developer", "engineer", "engineering", "font", "html", "javascript", "letter", "platform", "symbol", "text", "type" ] +}, { + "name" : "tram", + "tags" : [ "automobile", "car", "cars", "direction", "maps", "public", "rail", "subway", "train", "tram", "transportation", "vehicle" ] +}, { + "name" : "app_shortcut", + "tags" : [ "app", "bookmarked", "favorite", "highlight", "important", "marked", "mobile", "save", "saved", "shortcut", "software", "special", "star" ] +}, { + "name" : "data_saver_off", + "tags" : [ "analytics", "bar", "bars", "chart", "data", "diagram", "donut", "graph", "infographic", "measure", "metrics", "off", "on", "ring", "saver", "statistics", "tracking" ] +}, { + "name" : "laptop_windows", + "tags" : [ "Android", "OS", "chrome", "device", "display", "hardware", "iOS", "laptop", "mac", "monitor", "screen", "web", "window", "windows" ] +}, { + "name" : "doorbell", + "tags" : [ "alarm", "bell", "door", "doorbell", "home", "house", "ringing" ] +}, { + "name" : "hd", + "tags" : [ "alphabet", "character", "definition", "display", "font", "hd", "high", "letter", "movie", "movies", "resolution", "screen", "symbol", "text", "tv", "type" ] +}, { + "name" : "file_download_off", + "tags" : [ "arrow", "disabled", "down", "download", "drive", "enabled", "export", "file", "install", "off", "on", "save", "slash", "upload" ] +}, { + "name" : "apps_outage", + "tags" : [ "all", "applications", "apps", "circles", "collection", "components", "dots", "grid", "interface", "outage", "squares", "ui", "ux" ] +}, { + "name" : "taxi_alert", + "tags" : [ "!", "alert", "attention", "automobile", "cab", "car", "cars", "caution", "danger", "direction", "error", "exclamation", "important", "lyft", "maps", "mark", "notification", "public", "symbol", "taxi", "transportation", "uber", "vehicle", "warning", "yellow" ] +}, { + "name" : "breakfast_dining", + "tags" : [ "bakery", "bread", "breakfast", "butter", "dining", "food", "toast" ] +}, { + "name" : "brightness_medium", + "tags" : [ "auto", "brightness", "control", "medium", "mobile", "monitor", "phone", "sun" ] +}, { + "name" : "gradient", + "tags" : [ "color", "edit", "editing", "effect", "filter", "gradient", "image", "images", "photography", "picture", "pictures" ] +}, { + "name" : "swipe_left", + "tags" : [ "arrow", "arrows", "finger", "hand", "hit", "left", "navigation", "reject", "strike", "swing", "swipe", "take" ] +}, { + "name" : "soup_kitchen", + "tags" : [ "breakfast", "brunch", "dining", "food", "kitchen", "lunch", "meal", "soup" ] +}, { + "name" : "voice_over_off", + "tags" : [ "account", "disabled", "enabled", "face", "human", "off", "on", "over", "people", "person", "profile", "recording", "slash", "speak", "speaking", "speech", "transcript", "user", "voice" ] +}, { + "name" : "water_damage", + "tags" : [ "architecture", "building", "damage", "drop", "droplet", "estate", "house", "leak", "plumbing", "real", "residence", "residential", "shelter", "water" ] +}, { + "name" : "abc", + "tags" : [ "alphabet", "character", "font", "letter", "symbol", "text", "type" ] +}, { + "name" : "data_saver_on", + "tags" : [ "+", "add", "analytics", "chart", "data", "diagram", "graph", "infographic", "measure", "metrics", "new", "on", "plus", "ring", "saver", "statistics", "symbol", "tracking" ] +}, { + "name" : "signal_wifi_0_bar", + "tags" : [ "0", "bar", "cell", "cellular", "data", "internet", "mobile", "network", "phone", "signal", "wifi", "wireless" ] +}, { + "name" : "brightness_low", + "tags" : [ "auto", "brightness", "control", "low", "mobile", "monitor", "phone", "sun" ] +}, { + "name" : "device_unknown", + "tags" : [ "?", "Android", "OS", "assistance", "cell", "device", "hardware", "help", "iOS", "info", "information", "mobile", "phone", "punctuation", "question mark", "support", "symbol", "tablet", "unknown" ] +}, { + "name" : "fire_extinguisher", + "tags" : [ "emergency", "extinguisher", "fire", "water" ] +}, { + "name" : "fitbit", + "tags" : [ "athlete", "athletic", "exercise", "fitbit", "fitness", "hobby", "logo" ] +}, { + "name" : "bedroom_child", + "tags" : [ "bed", "bedroom", "child", "children", "furniture", "home", "hotel", "house", "kid", "night", "pillows", "rest", "room", "size", "sleep", "twin", "young" ] +}, { + "name" : "closed_caption_off", + "tags" : [ "accessible", "alphabet", "caption", "cc", "character", "closed", "decoder", "font", "language", "letter", "media", "movies", "off", "outline", "subtitle", "subtitles", "symbol", "text", "tv", "type" ] +}, { + "name" : "bluetooth_searching", + "tags" : [ "bluetooth", "connection", "device", "paring", "search", "searching", "symbol" ] +}, { + "name" : "content_paste_off", + "tags" : [ "clipboard", "content", "disabled", "doc", "document", "enabled", "file", "off", "on", "paste", "slash" ] +}, { + "name" : "hexagon", + "tags" : [ "hexagon", "shape", "six sides" ] +}, { + "name" : "tap_and_play", + "tags" : [ "Android", "OS wifi", "cell", "connection", "device", "hardware", "iOS", "internet", "mobile", "network", "phone", "play", "signal", "tablet", "tap", "to", "wireless" ] +}, { + "name" : "domain_add", + "tags" : [ "+", "add", "apartment", "architecture", "building", "business", "domain", "estate", "home", "new", "place", "plus", "real", "residence", "residential", "shelter", "symbol", "web", "www" ] +}, { + "name" : "signpost", + "tags" : [ "arrow", "direction", "left", "maps", "right", "signal", "signs", "street", "traffic" ] +}, { + "name" : "screenshot", + "tags" : [ "Android", "OS", "cell", "crop", "device", "hardware", "iOS", "mobile", "phone", "screen", "screenshot", "tablet" ] +}, { + "name" : "network_cell", + "tags" : [ "cell", "cellular", "data", "internet", "mobile", "network", "phone", "speed", "wifi", "wireless" ] +}, { + "name" : "repeat_on", + "tags" : [ "arrow", "arrows", "control", "controls", "media", "music", "on", "repeat", "video" ] +}, { + "name" : "charging_station", + "tags" : [ "Android", "OS", "battery", "bolt", "cell", "charging", "device", "electric", "hardware", "iOS", "lightning", "mobile", "phone", "station", "tablet", "thunderbolt" ] +}, { + "name" : "grid_4x4", + "tags" : [ "4", "by", "grid", "layout", "lines", "space" ] +}, { + "name" : "assistant_photo", + "tags" : [ "assistant", "flag", "photo", "recommendation", "smart", "star", "suggestion" ] +}, { + "name" : "carpenter", + "tags" : [ "building", "carpenter", "construction", "cutting", "handyman", "repair", "saw", "tool" ] +}, { + "name" : "private_connectivity", + "tags" : [ "connectivity", "lock", "locked", "password", "privacy", "private", "protection", "safety", "secure", "security" ] +}, { + "name" : "mobiledata_off", + "tags" : [ "arrow", "data", "disabled", "down", "enabled", "internet", "mobile", "network", "off", "on", "slash", "speed", "up", "wifi", "wireless" ] +}, { + "name" : "atm", + "tags" : [ "alphabet", "atm", "automated", "bill", "card", "cart", "cash", "character", "coin", "commerce", "credit", "currency", "dollars", "font", "letter", "machine", "money", "online", "pay", "payment", "shopping", "symbol", "teller", "text", "type" ] +}, { + "name" : "rv_hookup", + "tags" : [ "arrow", "attach", "automobile", "automotive", "back", "car", "cars", "connect", "direction", "hookup", "left", "maps", "public", "right", "rv", "trailer", "transportation", "travel", "truck", "van", "vehicle" ] +}, { + "name" : "replay_30", + "tags" : [ "30", "arrow", "arrows", "control", "controls", "digit", "music", "number", "refresh", "renew", "repeat", "replay", "symbol", "thirty", "video" ] +}, { + "name" : "offline_share", + "tags" : [ "Android", "OS", "arrow", "cell", "connect", "device", "direction", "hardware", "iOS", "link", "mobile", "multiple", "offline", "phone", "right", "share", "tablet" ] +}, { + "name" : "settings_input_svideo", + "tags" : [ "cable", "connection", "connectivity", "definition", "input", "plug", "plugin", "points", "settings", "standard", "svideo", "video" ] +}, { + "name" : "soap", + "tags" : [ "bathroom", "clean", "fingers", "gesture", "hand", "soap", "wash", "wc" ] +}, { + "name" : "baby_changing_station", + "tags" : [ "babies", "baby", "bathroom", "body", "changing", "child", "children", "father", "human", "infant", "kids", "mother", "newborn", "people", "person", "station", "toddler", "wc", "young" ] +}, { + "name" : "sports_cricket", + "tags" : [ "athlete", "athletic", "ball", "bat", "cricket", "entertainment", "exercise", "game", "hobby", "social", "sports" ] +}, { + "name" : "ad_units", + "tags" : [ "Android", "OS", "ad", "banner", "cell", "device", "hardware", "iOS", "mobile", "notification", "notifications", "phone", "tablet", "top", "units" ] +}, { + "name" : "wb_twilight", + "tags" : [ "balance", "light", "lighting", "noon", "sun", "sunset", "twilight", "wb", "white" ] +}, { + "name" : "no_encryption", + "tags" : [ "disabled", "enabled", "encryption", "lock", "no", "off", "on", "password", "safety", "security", "slash" ] +}, { + "name" : "table_bar", + "tags" : [ "bar", "cafe", "round", "table" ] +}, { + "name" : "diversity_2", + "tags" : [ "committee", "diverse", "diversity", "family", "friends", "group", "groups", "heart", "humans", "network", "people", "persons", "social", "team" ] +}, { + "name" : "subway", + "tags" : [ "automobile", "bike", "car", "cars", "maps", "rail", "scooter", "subway", "train", "transportation", "travel", "tunnel", "underground", "vehicle", "vespa" ] +}, { + "name" : "browser_updated", + "tags" : [ "Android", "OS", "arrow", "browser", "chrome", "desktop", "device", "display", "download", "hardware", "iOS", "mac", "monitor", "screen", "updated", "web", "window" ] +}, { + "name" : "currency_pound", + "tags" : [ "bill", "card", "cash", "coin", "commerce", "cost", "credit", "currency", "dollars", "finance", "money", "online", "pay", "payment", "pound", "price", "shopping", "symbol" ] +}, { + "name" : "transit_enterexit", + "tags" : [ "arrow", "direction", "enterexit", "maps", "navigation", "route", "transit", "transportation" ] +}, { + "name" : "contrast", + "tags" : [ "black", "contrast", "edit", "editing", "effect", "filter", "grayscale", "image", "images", "photography", "picture", "pictures", "settings", "white" ] +}, { + "name" : "lightbulb_circle", + "tags" : [ "alert", "announcement", "idea", "info", "information", "light", "lightbulb" ] +}, { + "name" : "rectangle", + "tags" : [ "four sides", "parallelograms", "polygons", "quadrilaterals", "recangle", "shape" ] +}, { + "name" : "call_merge", + "tags" : [ "arrow", "call", "device", "merge", "mobile" ] +}, { + "name" : "hide_image", + "tags" : [ "disabled", "enabled", "hide", "image", "landscape", "mountain", "mountains", "off", "on", "photo", "photography", "picture", "slash" ] +}, { + "name" : "shield_moon", + "tags" : [ "certified", "do not disturb", "moon", "night", "privacy", "private", "protect", "protection", "security", "shield", "verified" ] +}, { + "name" : "group_off", + "tags" : [ "body", "club", "collaboration", "crowd", "gathering", "group", "human", "meeting", "off", "people", "person", "social", "teams" ] +}, { + "name" : "music_off", + "tags" : [ "audio", "audiotrack", "disabled", "enabled", "key", "music", "note", "off", "on", "slash", "sound", "track" ] +}, { + "name" : "bluetooth_disabled", + "tags" : [ "bluetooth", "cast", "connect", "connection", "device", "disabled", "enabled", "off", "offline", "on", "paring", "slash", "streaming", "symbol", "wireless" ] +}, { + "name" : "flip_to_back", + "tags" : [ "arrange", "arrangement", "back", "flip", "format", "front", "layout", "move", "order", "sort", "to" ] +}, { + "name" : "sd_card", + "tags" : [ "camera", "card", "digital", "memory", "photos", "sd", "secure", "storage" ] +}, { + "name" : "exposure_plus_1", + "tags" : [ "1", "add", "brightness", "contrast", "digit", "edit", "editing", "effect", "exposure", "image", "number", "photo", "photography", "plus", "settings", "symbol" ] +}, { + "name" : "view_array", + "tags" : [ "array", "design", "format", "grid", "layout", "view", "website" ] +}, { + "name" : "sports_mma", + "tags" : [ "arts", "athlete", "athletic", "boxing", "combat", "entertainment", "exercise", "fighting", "game", "glove", "hobby", "martial", "mixed", "mma", "social", "sports" ] +}, { + "name" : "straight", + "tags" : [ "arrow", "arrows", "direction", "directions", "maps", "navigation", "path", "route", "sign", "straight", "traffic", "up" ] +}, { + "name" : "thermostat_auto", + "tags" : [ "A", "auto", "celsius", "fahrenheit", "meter", "temp", "temperature", "thermometer", "thermostat" ] +}, { + "name" : "mobile_screen_share", + "tags" : [ "Android", "OS", "cast", "cell", "device", "hardware", "iOS", "mirror", "mobile", "monitor", "phone", "screen", "screencast", "share", "stream", "streaming", "tablet", "tv", "wireless" ] +}, { + "name" : "phone_missed", + "tags" : [ "arrow", "call", "cell", "contact", "device", "hardware", "missed", "mobile", "phone", "telephone" ] +}, { + "name" : "brunch_dining", + "tags" : [ "breakfast", "brunch", "champagne", "dining", "drink", "food", "lunch", "meal" ] +}, { + "name" : "featured_video", + "tags" : [ "advertised", "advertisement", "featured", "highlighted", "recommended", "video", "watch" ] +}, { + "name" : "merge", + "tags" : [ "arrow", "arrows", "direction", "directions", "maps", "merge", "navigation", "path", "route", "sign", "traffic" ] +}, { + "name" : "open_in_new_off", + "tags" : [ "arrow", "box", "disabled", "enabled", "export", "in", "new", "off", "on", "open", "slash", "window" ] +}, { + "name" : "hdr_auto", + "tags" : [ "A", "alphabet", "auto", "camera", "character", "circle", "dynamic", "font", "hdr", "high", "letter", "photo", "range", "symbol", "text", "type" ] +}, { + "name" : "join_inner", + "tags" : [ "circle", "command", "inner", "join", "matching", "overlap", "sql", "values" ] +}, { + "name" : "solar_power", + "tags" : [ "eco", "energy", "heat", "nest", "power", "solar", "sun", "sunny" ] +}, { + "name" : "crop_16_9", + "tags" : [ "16", "9", "adjust", "adjustments", "area", "by", "crop", "edit", "editing", "frame", "image", "images", "photo", "photos", "rectangle", "settings", "size", "square" ] +}, { + "name" : "swipe_right", + "tags" : [ "accept", "arrows", "direction", "finger", "hands", "hit", "navigation", "right", "strike", "swing", "swpie", "take" ] +}, { + "name" : "phonelink_erase", + "tags" : [ "Android", "OS", "cancel", "cell", "close", "connection", "device", "erase", "exit", "hardware", "iOS", "mobile", "no", "phone", "phonelink", "remove", "stop", "tablet", "x" ] +}, { + "name" : "smoke_free", + "tags" : [ "cigarette", "disabled", "enabled", "free", "never", "no", "off", "on", "places", "prohibited", "slash", "smoke", "smoking", "tobacco", "warning", "zone" ] +}, { + "name" : "install_desktop", + "tags" : [ "Android", "OS", "chrome", "desktop", "device", "display", "fix", "hardware", "iOS", "install", "mac", "monitor", "place", "pwa", "screen", "web", "window" ] +}, { + "name" : "shutter_speed", + "tags" : [ "aperture", "camera", "duration", "image", "lens", "photo", "photography", "photos", "picture", "setting", "shutter", "speed", "stop", "time", "timer", "watch" ] +}, { + "name" : "keyboard_hide", + "tags" : [ "arrow", "computer", "device", "down", "hardware", "hide", "input", "keyboard", "keypad", "text" ] +}, { + "name" : "exposure", + "tags" : [ "add", "brightness", "contrast", "edit", "editing", "effect", "exposure", "image", "minus", "photo", "photography", "picture", "plus", "settings", "subtract" ] +}, { + "name" : "nordic_walking", + "tags" : [ "athlete", "athletic", "body", "entertainment", "exercise", "hiking", "hobby", "human", "nordic", "people", "person", "social", "sports", "travel", "walker", "walking" ] +}, { + "name" : "umbrella", + "tags" : [ "beach", "protection", "rain", "sun", "sunny", "umbrella" ] +}, { + "name" : "move_down", + "tags" : [ "arrow", "direction", "down", "jump", "move", "navigation", "transfer" ] +}, { + "name" : "filter_2", + "tags" : [ "2", "digit", "edit", "editing", "effect", "filter", "image", "images", "multiple", "number", "photography", "picture", "pictures", "settings", "stack", "symbol" ] +}, { + "name" : "photo_album", + "tags" : [ "album", "archive", "bookmark", "image", "label", "library", "mountain", "mountains", "photo", "photography", "picture", "ribbon", "save", "tag" ] +}, { + "name" : "security_update_good", + "tags" : [ "Android", "OS", "checkmark", "device", "good", "hardware", "iOS", "mobile", "ok", "phone", "security", "tablet", "tick", "update" ] +}, { + "name" : "ssid_chart", + "tags" : [ "chart", "graph", "lines", "network", "ssid", "wifi" ] +}, { + "name" : "score", + "tags" : [ "2k", "alphabet", "analytics", "bar", "bars", "character", "chart", "data", "diagram", "digit", "font", "graph", "infographic", "letter", "measure", "metrics", "number", "score", "statistics", "symbol", "text", "tracking", "type" ] +}, { + "name" : "swipe_up", + "tags" : [ "arrows", "direction", "disable", "enable", "finger", "hands", "hit", "navigation", "strike", "swing", "swpie", "take", "up" ] +}, { + "name" : "battery_4_bar", + "tags" : [ "4", "bar", "battery", "cell", "charge", "mobile", "power" ] +}, { + "name" : "all_out", + "tags" : [ "all", "circle", "out", "shape" ] +}, { + "name" : "battery_unknown", + "tags" : [ "?", "assistance", "battery", "cell", "charge", "help", "info", "information", "mobile", "power", "punctuation", "question mark", "support", "symbol", "unknown" ] +}, { + "name" : "sports_golf", + "tags" : [ "athlete", "athletic", "ball", "club", "entertainment", "exercise", "game", "golf", "golfer", "golfing", "hobby", "social", "sports" ] +}, { + "name" : "sports_martial_arts", + "tags" : [ "arts", "athlete", "athletic", "entertainment", "exercise", "hobby", "human", "karate", "martial", "people", "person", "social", "sports" ] +}, { + "name" : "filter_tilt_shift", + "tags" : [ "blur", "center", "edit", "editing", "effect", "filter", "focus", "image", "images", "photography", "picture", "pictures", "shift", "tilt" ] +}, { + "name" : "electric_bike", + "tags" : [ "bike", "electric", "electricity", "maps", "scooter", "transportation", "travel", "vespa" ] +}, { + "name" : "border_all", + "tags" : [ "all", "border", "doc", "edit", "editing", "editor", "sheet", "spreadsheet", "stroke", "text", "type", "writing" ] +}, { + "name" : "auto_mode", + "tags" : [ "ai", "around", "arrow", "arrows", "artificial", "auto", "automatic", "automation", "custom", "direction", "genai", "inprogress", "intelligence", "load", "loading refresh", "magic", "mode", "navigation", "nest", "renew", "rotate", "smart", "spark", "sparkle", "star", "turn" ] +}, { + "name" : "hvac", + "tags" : [ "air", "conditioning", "heating", "hvac", "ventilation" ] +}, { + "name" : "scanner", + "tags" : [ "copy", "device", "hardware", "machine", "scan", "scanner" ] +}, { + "name" : "shuffle_on", + "tags" : [ "arrow", "arrows", "control", "controls", "music", "on", "random", "shuffle", "video" ] +}, { + "name" : "wifi_calling_3", + "tags" : [ "3", "calling", "cell", "cellular", "data", "internet", "mobile", "network", "phone", "speed", "wifi", "wireless" ] +}, { + "name" : "signal_wifi_off", + "tags" : [ "cell", "cellular", "data", "disabled", "enabled", "internet", "mobile", "network", "off", "on", "phone", "signal", "slash", "speed", "wifi", "wireless" ] +}, { + "name" : "girl", + "tags" : [ "body", "female", "gender", "girl", "human", "lady", "people", "person", "social", "symbol", "woman", "women" ] +}, { + "name" : "shop_2", + "tags" : [ "2", "add", "arrow", "buy", "cart", "google", "play", "purchase", "shop", "shopping" ] +}, { + "name" : "hdr_strong", + "tags" : [ "circles", "dots", "dynamic", "enhance", "hdr", "high", "range", "strong" ] +}, { + "name" : "directions_transit", + "tags" : [ "automobile", "car", "cars", "direction", "directions", "maps", "public", "rail", "subway", "train", "transit", "transportation", "vehicle" ] +}, { + "name" : "label_off", + "tags" : [ "disabled", "enabled", "favorite", "indent", "label", "library", "mail", "off", "on", "remember", "save", "slash", "stamp", "sticker", "tag", "wing" ] +}, { + "name" : "tablet", + "tags" : [ "Android", "OS", "device", "hardware", "iOS", "ipad", "mobile", "tablet", "web" ] +}, { + "name" : "5g", + "tags" : [ "5g", "alphabet", "cellular", "character", "data", "digit", "font", "letter", "mobile", "network", "number", "phone", "signal", "speed", "symbol", "text", "type", "wifi" ] +}, { + "name" : "vrpano", + "tags" : [ "angle", "image", "landscape", "mountain", "mountains", "panorama", "photo", "photography", "picture", "view", "vrpano", "wide" ] +}, { + "name" : "forward_30", + "tags" : [ "30", "arrow", "control", "controls", "digit", "fast", "forward", "music", "number", "seconds", "symbol", "video" ] +}, { + "name" : "battery_0_bar", + "tags" : [ "0", "bar", "battery", "cell", "charge", "mobile", "power" ] +}, { + "name" : "airline_seat_recline_extra", + "tags" : [ "airline", "body", "extra", "feet", "human", "leg", "legroom", "people", "person", "seat", "sitting", "space", "travel" ] +}, { + "name" : "looks", + "tags" : [ "circle", "half", "looks", "rainbow" ] +}, { + "name" : "linked_camera", + "tags" : [ "camera", "connect", "connection", "lens", "linked", "network", "photo", "photography", "picture", "signal", "signals", "sync", "wireless" ] +}, { + "name" : "paragliding", + "tags" : [ "athlete", "athletic", "body", "entertainment", "exercise", "fly", "gliding", "hobby", "human", "parachute", "paragliding", "people", "person", "sky", "skydiving", "social", "sports", "travel" ] +}, { + "name" : "electric_scooter", + "tags" : [ "bike", "electric", "maps", "scooter", "transportation", "vehicle", "vespa" ] +}, { + "name" : "settings_system_daydream", + "tags" : [ "backup", "cloud", "daydream", "drive", "settings", "storage", "system" ] +}, { + "name" : "format_indent_decrease", + "tags" : [ "align", "alignment", "decrease", "doc", "edit", "editing", "editor", "format", "indent", "indentation", "paragraph", "sheet", "spreadsheet", "text", "type", "writing" ] +}, { + "name" : "tapas", + "tags" : [ "appetizer", "brunch", "dinner", "food", "lunch", "restaurant", "snack", "tapas" ] +}, { + "name" : "brightness_3", + "tags" : [ "3", "brightness", "circle", "control", "crescent", "level", "moon", "screen" ] +}, { + "name" : "tab_unselected", + "tags" : [ "browser", "computer", "document", "documents", "folder", "internet", "tab", "tabs", "unselected", "web", "website", "window", "windows" ] +}, { + "name" : "density_small", + "tags" : [ "density", "horizontal", "lines", "rule", "rules", "small" ] +}, { + "name" : "blur_circular", + "tags" : [ "blur", "circle", "circular", "dots", "edit", "editing", "effect", "enhance", "filter" ] +}, { + "name" : "rice_bowl", + "tags" : [ "bowl", "dinner", "food", "lunch", "meal", "restaurant", "rice" ] +}, { + "name" : "rounded_corner", + "tags" : [ "adjust", "corner", "edit", "rounded", "shape", "square", "transform" ] +}, { + "name" : "person_add_disabled", + "tags" : [ "+", "account", "add", "disabled", "enabled", "face", "human", "new", "off", "offline", "on", "people", "person", "plus", "profile", "slash", "symbol", "user" ] +}, { + "name" : "music_video", + "tags" : [ "band", "music", "recording", "screen", "tv", "video", "watch" ] +}, { + "name" : "looks_6", + "tags" : [ "6", "digit", "looks", "numbers", "square", "symbol" ] +}, { + "name" : "do_not_touch", + "tags" : [ "disabled", "do", "enabled", "fingers", "gesture", "hand", "not", "off", "on", "slash", "touch" ] +}, { + "name" : "playlist_add_circle", + "tags" : [ "add", "album", "artist", "audio", "cd", "check", "circle", "collection", "list", "mark", "music", "playlist", "record", "sound", "track" ] +}, { + "name" : "domain_disabled", + "tags" : [ "apartment", "architecture", "building", "business", "company", "disabled", "domain", "enabled", "estate", "home", "internet", "maps", "off", "office", "offline", "on", "place", "real", "residence", "residential", "slash", "web", "website" ] +}, { + "name" : "flash_auto", + "tags" : [ "a", "auto", "bolt", "electric", "fast", "flash", "lightning", "thunderbolt" ] +}, { + "name" : "6_ft_apart", + "tags" : [ "6", "apart", "body", "covid", "distance", "feet", "ft", "human", "people", "person", "social" ] +}, { + "name" : "signal_wifi_bad", + "tags" : [ "bad", "bar", "cancel", "cell", "cellular", "close", "data", "exit", "internet", "mobile", "network", "no", "phone", "quit", "remove", "signal", "stop", "wifi", "wireless", "x" ] +}, { + "name" : "crisis_alert", + "tags" : [ "!", "alert", "attention", "bullseye", "caution", "crisis", "danger", "error", "exclamation", "important", "mark", "notification", "symbol", "target", "warning" ] +}, { + "name" : "queue_play_next", + "tags" : [ "+", "add", "arrow", "desktop", "device", "display", "hardware", "monitor", "new", "next", "play", "plus", "queue", "screen", "steam", "symbol", "tv" ] +}, { + "name" : "format_clear", + "tags" : [ "T", "alphabet", "character", "clear", "disabled", "doc", "edit", "editing", "editor", "enabled", "font", "format", "letter", "off", "on", "sheet", "slash", "spreadsheet", "style", "symbol", "text", "type", "writing" ] +}, { + "name" : "bus_alert", + "tags" : [ "!", "alert", "attention", "automobile", "bus", "car", "cars", "caution", "danger", "error", "exclamation", "important", "maps", "mark", "notification", "symbol", "transportation", "vehicle", "warning" ] +}, { + "name" : "party_mode", + "tags" : [ "camera", "lens", "mode", "party", "photo", "photography", "picture" ] +}, { + "name" : "snowboarding", + "tags" : [ "athlete", "athletic", "body", "entertainment", "exercise", "hobby", "human", "people", "person", "snow", "snowboarding", "social", "sports", "travel", "winter" ] +}, { + "name" : "text_rotate_vertical", + "tags" : [ "A", "alphabet", "arrow", "character", "down", "field", "font", "letter", "move", "rotate", "symbol", "text", "type", "vertical" ] +}, { + "name" : "motion_photos_auto", + "tags" : [ "A", "alphabet", "animation", "auto", "automatic", "character", "circle", "font", "gif", "letter", "live", "motion", "photos", "symbol", "text", "type", "video" ] +}, { + "name" : "crop_portrait", + "tags" : [ "adjust", "adjustments", "area", "crop", "edit", "editing", "frame", "image", "images", "photo", "photos", "portrait", "rectangle", "settings", "size", "square" ] +}, { + "name" : "thunderstorm", + "tags" : [ "bolt", "climate", "cloud", "cloudy", "lightning", "rain", "rainfall", "rainstorm", "storm", "thunder", "thunderstorm", "weather" ] +}, { + "name" : "battery_6_bar", + "tags" : [ "6", "bar", "battery", "cell", "charge", "mobile", "power" ] +}, { + "name" : "space_bar", + "tags" : [ "bar", "keyboard", "line", "space" ] +}, { + "name" : "replay_5", + "tags" : [ "5", "arrow", "arrows", "control", "controls", "digit", "five", "music", "number", "refresh", "renew", "repeat", "replay", "symbol", "video" ] +}, { + "name" : "local_car_wash", + "tags" : [ "automobile", "car", "cars", "local", "maps", "transportation", "travel", "vehicle", "wash" ] +}, { + "name" : "folder_delete", + "tags" : [ "bin", "can", "data", "delete", "doc", "document", "drive", "file", "folder", "folders", "garbage", "remove", "sheet", "slide", "storage", "trash" ] +}, { + "name" : "data_thresholding", + "tags" : [ "data", "hidden", "privacy", "thresholding", "thresold" ] +}, { + "name" : "connecting_airports", + "tags" : [ "airplane", "airplanes", "airport", "airports", "connecting", "flight", "plane", "transportation", "travel", "trip" ] +}, { + "name" : "access_alarms", + "tags" : [ ] +}, { + "name" : "tty", + "tags" : [ "call", "cell", "contact", "deaf", "device", "hardware", "impaired", "mobile", "phone", "speech", "talk", "telephone", "text", "tty" ] +}, { + "name" : "audio_file", + "tags" : [ "audio", "doc", "document", "key", "music", "note", "sound", "track" ] +}, { + "name" : "egg", + "tags" : [ "breakfast", "brunch", "egg", "food" ] +}, { + "name" : "balcony", + "tags" : [ "architecture", "balcony", "doors", "estate", "home", "house", "maps", "out", "outside", "place", "real", "residence", "residential", "stay", "terrace", "window" ] +}, { + "name" : "kitesurfing", + "tags" : [ "athlete", "athletic", "beach", "body", "entertainment", "exercise", "hobby", "human", "kitesurfing", "people", "person", "social", "sports", "surf", "travel", "water" ] +}, { + "name" : "call_missed_outgoing", + "tags" : [ "arrow", "call", "device", "missed", "mobile", "outgoing" ] +}, { + "name" : "local_hotel", + "tags" : [ "body", "hotel", "human", "local", "people", "person", "sleep", "stay", "travel", "trip" ] +}, { + "name" : "text_increase", + "tags" : [ "+", "add", "alphabet", "character", "font", "increase", "letter", "new", "plus", "resize", "symbol", "text", "type" ] +}, { + "name" : "speaker_phone", + "tags" : [ "Android", "OS", "cell", "device", "hardware", "iOS", "mobile", "phone", "sound", "speaker", "tablet", "volume" ] +}, { + "name" : "no_food", + "tags" : [ "disabled", "drink", "enabled", "fastfood", "food", "hamburger", "meal", "no", "off", "on", "slash" ] +}, { + "name" : "brightness_2", + "tags" : [ "2", "brightness", "circle", "control", "crescent", "level", "moon", "screen" ] +}, { + "name" : "mode_of_travel", + "tags" : [ "arrow", "destination", "direction", "location", "maps", "mode", "of", "pin", "place", "stop", "transportation", "travel", "trip" ] +}, { + "name" : "format_line_spacing", + "tags" : [ "align", "alignment", "doc", "edit", "editing", "editor", "format", "line", "sheet", "spacing", "spreadsheet", "text", "type", "writing" ] +}, { + "name" : "iso", + "tags" : [ "add", "edit", "editing", "effect", "image", "iso", "minus", "photography", "picture", "plus", "sensor", "shutter", "speed", "subtract" ] +}, { + "name" : "explore_off", + "tags" : [ "compass", "destination", "direction", "disabled", "east", "enabled", "explore", "location", "maps", "needle", "north", "off", "on", "slash", "south", "travel", "west" ] +}, { + "name" : "drive_file_move_rtl", + "tags" : [ "arrow", "arrows", "data", "direction", "doc", "document", "drive", "file", "folder", "folders", "left", "move", "rtl", "sheet", "side", "slide", "storage" ] +}, { + "name" : "cell_wifi", + "tags" : [ "cell", "connection", "data", "internet", "mobile", "network", "phone", "service", "signal", "wifi", "wireless" ] +}, { + "name" : "tonality", + "tags" : [ "circle", "edit", "editing", "filter", "image", "photography", "picture", "tonality" ] +}, { + "name" : "spoke", + "tags" : [ "connection", "network", "radius", "spoke" ] +}, { + "name" : "photo_filter", + "tags" : [ "ai", "artificial", "automatic", "automation", "custom", "filter", "filters", "genai", "image", "intelligence", "magic", "photo", "photography", "picture", "smart", "spark", "sparkle", "star" ] +}, { + "name" : "desktop_access_disabled", + "tags" : [ "Android", "OS", "access", "chrome", "desktop", "device", "disabled", "display", "enabled", "hardware", "iOS", "mac", "monitor", "off", "offline", "on", "screen", "slash", "web", "window" ] +}, { + "name" : "sports_gymnastics", + "tags" : [ "athlete", "athletic", "entertainment", "exercise", "gymnastics", "hobby", "social", "sports" ] +}, { + "name" : "houseboat", + "tags" : [ "architecture", "beach", "boat", "estate", "floating", "home", "house", "houseboat", "maps", "place", "real", "residence", "residential", "sea", "stay", "traveling", "vacation" ] +}, { + "name" : "fence", + "tags" : [ "backyard", "barrier", "boundaries", "boundary", "fence", "home", "house", "protection", "yard" ] +}, { + "name" : "commit", + "tags" : [ "accomplish", "bind", "circle", "commit", "dedicate", "execute", "line", "perform", "pledge" ] +}, { + "name" : "photo_size_select_small", + "tags" : [ "adjust", "album", "edit", "editing", "image", "large", "library", "mountain", "mountains", "photo", "photography", "picture", "select", "size", "small" ] +}, { + "name" : "signal_wifi_connected_no_internet_4", + "tags" : [ "4", "cell", "cellular", "connected", "data", "internet", "mobile", "network", "no", "offline", "phone", "signal", "wifi", "wireless", "x" ] +}, { + "name" : "horizontal_distribute", + "tags" : [ "alignment", "distribute", "format", "horizontal", "layout", "lines", "paragraph", "rule", "rules", "style", "text" ] +}, { + "name" : "report_off", + "tags" : [ "!", "alert", "attention", "caution", "danger", "disabled", "enabled", "error", "exclamation", "important", "mark", "notification", "octagon", "off", "offline", "on", "report", "slash", "symbol", "warning" ] +}, { + "name" : "polyline", + "tags" : [ "compose", "create", "design", "draw", "line", "polyline", "vector" ] +}, { + "name" : "art_track", + "tags" : [ "album", "art", "artist", "audio", "image", "music", "photo", "photography", "picture", "sound", "track", "tracks" ] +}, { + "name" : "crop_7_5", + "tags" : [ "5", "7", "adjust", "adjustments", "area", "by", "crop", "editing", "frame", "image", "images", "photo", "photos", "rectangle", "settings", "size", "square" ] +}, { + "name" : "filter_hdr", + "tags" : [ "camera", "edit", "editing", "effect", "filter", "hdr", "image", "mountain", "mountains", "photo", "photography", "picture" ] +}, { + "name" : "text_rotation_none", + "tags" : [ "A", "alphabet", "arrow", "character", "field", "font", "letter", "move", "none", "rotate", "symbol", "text", "type" ] +}, { + "name" : "battery_3_bar", + "tags" : [ "3", "bar", "battery", "cell", "charge", "mobile", "power" ] +}, { + "name" : "align_vertical_bottom", + "tags" : [ "align", "alignment", "bottom", "format", "layout", "lines", "paragraph", "rule", "rules", "style", "text", "vertical" ] +}, { + "name" : "stop_screen_share", + "tags" : [ "Android", "OS", "arrow", "cast", "chrome", "device", "disabled", "display", "enabled", "hardware", "iOS", "laptop", "mac", "mirror", "monitor", "off", "offline", "on", "screen", "share", "slash", "steam", "stop", "streaming", "web", "window" ] +}, { + "name" : "imagesearch_roller", + "tags" : [ "art", "image", "imagesearch", "paint", "roller", "search" ] +}, { + "name" : "bento", + "tags" : [ "bento", "box", "dinner", "food", "lunch", "meal", "restaurant", "takeout" ] +}, { + "name" : "rotate_90_degrees_cw", + "tags" : [ "90", "arrow", "arrows", "ccw", "degrees", "direction", "edit", "editing", "image", "photo", "rotate", "turn" ] +}, { + "name" : "install_mobile", + "tags" : [ "Android", "OS", "cell", "device", "hardware", "iOS", "install", "mobile", "phone", "pwa", "tablet" ] +}, { + "name" : "hearing_disabled", + "tags" : [ "accessibility", "accessible", "aid", "disabled", "ear", "enabled", "handicap", "hearing", "help", "impaired", "listen", "off", "on", "slash", "sound", "volume" ] +}, { + "name" : "video_file", + "tags" : [ "camera", "doc", "document", "film", "filming", "hardware", "image", "motion", "picture", "video", "videography" ] +}, { + "name" : "mms", + "tags" : [ "bubble", "chat", "comment", "communicate", "feedback", "image", "landscape", "message", "mms", "mountain", "mountains", "multimedia", "photo", "photography", "picture", "speech" ] +}, { + "name" : "crop_rotate", + "tags" : [ "adjust", "adjustments", "area", "arrow", "arrows", "crop", "edit", "editing", "frame", "image", "images", "photo", "photos", "rotate", "settings", "size", "turn" ] +}, { + "name" : "wheelchair_pickup", + "tags" : [ "accessibility", "accessible", "body", "handicap", "help", "human", "person", "pickup", "wheelchair" ] +}, { + "name" : "aod", + "tags" : [ "Android", "OS", "always", "aod", "device", "display", "hardware", "homescreen", "iOS", "mobile", "on", "phone", "tablet" ] +}, { + "name" : "castle", + "tags" : [ "castle", "fort", "fortress", "mansion", "palace" ] +}, { + "name" : "interpreter_mode", + "tags" : [ "interpreter", "language", "microphone", "mode", "person", "speaking", "symbol" ] +}, { + "name" : "access_alarm", + "tags" : [ ] +}, { + "name" : "forward_5", + "tags" : [ "10", "5", "arrow", "control", "controls", "digit", "fast", "forward", "music", "number", "seconds", "symbol", "video" ] +}, { + "name" : "add_to_home_screen", + "tags" : [ "Android", "OS", "add to", "arrow", "cell", "device", "hardware", "home", "iOS", "mobile", "phone", "screen", "tablet", "up" ] +}, { + "name" : "not_accessible", + "tags" : [ "accessibility", "accessible", "body", "handicap", "help", "human", "not", "person", "wheelchair" ] +}, { + "name" : "signal_cellular_0_bar", + "tags" : [ "0", "bar", "cell", "cellular", "data", "internet", "mobile", "network", "phone", "signal", "speed", "wifi", "wireless" ] +}, { + "name" : "stadium", + "tags" : [ "activity", "amphitheater", "arena", "coliseum", "event", "local", "stadium", "star", "things", "ticket" ] +}, { + "name" : "photo_size_select_large", + "tags" : [ "adjust", "album", "edit", "editing", "image", "large", "library", "mountain", "mountains", "photo", "photography", "picture", "select", "size" ] +}, { + "name" : "groups_3", + "tags" : [ "abstract", "body", "club", "collaboration", "crowd", "gathering", "groups", "human", "meeting", "people", "person", "social", "teams" ] +}, { + "name" : "snowshoeing", + "tags" : [ "body", "human", "people", "person", "snow", "snowshoe", "snowshoeing", "sports", "travel", "walking", "winter" ] +}, { + "name" : "view_kanban", + "tags" : [ "grid", "kanban", "layout", "pattern", "squares", "view" ] +}, { + "name" : "candlestick_chart", + "tags" : [ "analytics", "candlestick", "chart", "data", "diagram", "finance", "graph", "infographic", "measure", "metrics", "statistics", "tracking" ] +}, { + "name" : "filter_3", + "tags" : [ "3", "digit", "edit", "editing", "effect", "filter", "image", "images", "multiple", "number", "photography", "picture", "pictures", "settings", "stack", "symbol" ] +}, { + "name" : "arrow_outward", + "tags" : [ "app", "application", "arrow", "arrows", "components", "direction", "forward", "interface", "navigation", "right", "screen", "site", "ui", "ux", "web", "website" ] +}, { + "name" : "align_horizontal_center", + "tags" : [ "align", "alignment", "center", "format", "horizontal", "layout", "lines", "paragraph", "rule", "rules", "style", "text" ] +}, { + "name" : "flashlight_off", + "tags" : [ "disabled", "enabled", "flash", "flashlight", "light", "off", "on", "slash" ] +}, { + "name" : "security_update", + "tags" : [ "Android", "OS", "arrow", "device", "down", "download", "hardware", "iOS", "mobile", "phone", "security", "tablet", "update" ] +}, { + "name" : "iron", + "tags" : [ "appliance", "clothes", "electric", "iron", "ironing", "machine", "object" ] +}, { + "name" : "print_disabled", + "tags" : [ "disabled", "enabled", "off", "on", "paper", "print", "printer", "slash" ] +}, { + "name" : "pin_invoke", + "tags" : [ "action", "arrow", "dot", "invoke", "pin" ] +}, { + "name" : "speaker_group", + "tags" : [ "box", "electronic", "group", "loud", "multiple", "music", "sound", "speaker", "stereo", "system", "video" ] +}, { + "name" : "exposure_zero", + "tags" : [ "0", "brightness", "contrast", "digit", "edit", "editing", "effect", "exposure", "image", "number", "photo", "photography", "settings", "symbol", "zero" ] +}, { + "name" : "bungalow", + "tags" : [ "architecture", "bungalow", "cottage", "estate", "home", "house", "maps", "place", "real", "residence", "residential", "stay", "traveling" ] +}, { + "name" : "streetview", + "tags" : [ "maps", "street", "streetview", "view" ] +}, { + "name" : "swipe_down", + "tags" : [ "arrows", "direction", "disable", "down", "enable", "finger", "hands", "hit", "navigation", "strike", "swing", "swpie", "take" ] +}, { + "name" : "hdr_weak", + "tags" : [ "circles", "dots", "dynamic", "enhance", "hdr", "high", "range", "weak" ] +}, { + "name" : "css", + "tags" : [ "alphabet", "brackets", "character", "code", "css", "develop", "developer", "engineer", "engineering", "font", "html", "letter", "platform", "symbol", "text", "type" ] +}, { + "name" : "call_missed", + "tags" : [ "arrow", "call", "device", "missed", "mobile" ] +}, { + "name" : "gps_off", + "tags" : [ "destination", "direction", "disabled", "enabled", "gps", "location", "maps", "not fixed", "off", "offline", "on", "place", "pointer", "slash", "tracking" ] +}, { + "name" : "sports_hockey", + "tags" : [ "athlete", "athletic", "entertainment", "exercise", "game", "hobby", "hockey", "social", "sports", "sticks" ] +}, { + "name" : "ice_skating", + "tags" : [ "athlete", "athletic", "entertainment", "exercise", "hobby", "ice", "shoe", "skates", "skating", "social", "sports", "travel" ] +}, { + "name" : "keyboard_capslock", + "tags" : [ "arrow", "capslock", "keyboard", "up" ] +}, { + "name" : "earbuds", + "tags" : [ "accessory", "audio", "earbuds", "earphone", "headphone", "listen", "music", "sound" ] +}, { + "name" : "camera_front", + "tags" : [ "body", "camera", "front", "human", "lens", "mobile", "person", "phone", "photography", "portrait", "selfie" ] +}, { + "name" : "vertical_distribute", + "tags" : [ "alignment", "distribute", "format", "layout", "lines", "paragraph", "rule", "rules", "style", "text", "vertical" ] +}, { + "name" : "currency_ruble", + "tags" : [ "bill", "card", "cash", "coin", "commerce", "cost", "credit", "currency", "dollars", "finance", "money", "online", "pay", "payment", "price", "ruble", "shopping", "symbol" ] +}, { + "name" : "signal_wifi_statusbar_null", + "tags" : [ "cell", "cellular", "data", "internet", "mobile", "network", "null", "phone", "signal", "speed", "statusbar", "wifi", "wireless" ] +}, { + "name" : "align_horizontal_right", + "tags" : [ "align", "alignment", "format", "horizontal", "layout", "lines", "paragraph", "right", "rule", "rules", "style", "text" ] +}, { + "name" : "crop_5_4", + "tags" : [ "4", "5", "adjust", "adjustments", "area", "by", "crop", "edit", "editing settings", "frame", "image", "images", "photo", "photos", "rectangle", "size", "square" ] +}, { + "name" : "format_strikethrough", + "tags" : [ "alphabet", "character", "doc", "edit", "editing", "editor", "font", "format", "letter", "sheet", "spreadsheet", "strikethrough", "style", "symbol", "text", "type", "writing" ] +}, { + "name" : "face_6", + "tags" : [ "account", "emoji", "eyes", "face", "human", "lock", "log", "login", "logout", "people", "person", "profile", "recognition", "security", "social", "thumbnail", "unlock", "user" ] +}, { + "name" : "join_left", + "tags" : [ "circle", "command", "join", "left", "matching", "overlap", "sql", "values" ] +}, { + "name" : "explicit", + "tags" : [ "adult", "alphabet", "character", "content", "e", "explicit", "font", "language", "letter", "media", "movies", "music", "symbol", "text", "type" ] +}, { + "name" : "extension_off", + "tags" : [ "disabled", "enabled", "extended", "extension", "jigsaw", "off", "on", "piece", "puzzle", "shape", "slash" ] +}, { + "name" : "perm_camera_mic", + "tags" : [ "camera", "image", "microphone", "min", "perm", "photo", "photography", "picture", "speaker" ] +}, { + "name" : "sports_rugby", + "tags" : [ "athlete", "athletic", "ball", "entertainment", "exercise", "game", "hobby", "rugby", "social", "sports" ] +}, { + "name" : "pause_presentation", + "tags" : [ "app", "application desktop", "device", "pause", "present", "presentation", "screen", "share", "site", "slides", "web", "website", "window", "www" ] +}, { + "name" : "south_america", + "tags" : [ "continent", "landscape", "place", "region", "south america" ] +}, { + "name" : "sd_storage", + "tags" : [ "camera", "card", "data", "digital", "memory", "sd", "secure", "storage" ] +}, { + "name" : "superscript", + "tags" : [ "2", "doc", "edit", "editing", "editor", "gmail", "novitas", "sheet", "spreadsheet", "style", "superscript", "symbol", "text", "writing", "x" ] +}, { + "name" : "4g_mobiledata", + "tags" : [ "4g", "alphabet", "cellular", "character", "digit", "font", "letter", "mobile", "mobiledata", "network", "number", "phone", "signal", "speed", "symbol", "text", "type", "wifi" ] +}, { + "name" : "pinch", + "tags" : [ "arrow", "arrows", "compress", "direction", "finger", "grasp", "hand", "navigation", "nip", "pinch", "squeeze", "tweak" ] +}, { + "name" : "lock_person", + "tags" : [ ] +}, { + "name" : "grid_3x3", + "tags" : [ "3", "grid", "layout", "line", "space" ] +}, { + "name" : "mark_unread_chat_alt", + "tags" : [ "bubble", "chat", "circle", "comment", "communicate", "mark", "message", "notification", "speech", "unread" ] +}, { + "name" : "web_stories", + "tags" : [ "google", "images", "logo", "stories", "web" ] +}, { + "name" : "safety_check", + "tags" : [ "certified", "check", "clock", "privacy", "private", "protect", "protection", "safety", "schedule", "security", "shield", "time", "verified" ] +}, { + "name" : "filter_frames", + "tags" : [ "boarders", "border", "camera", "center", "edit", "editing", "effect", "filter", "filters", "focus", "frame", "frames", "image", "options", "photo", "photography", "picture" ] +}, { + "name" : "spatial_audio_off", + "tags" : [ "audio", "disabled", "enabled", "music", "note", "off", "offline", "on", "slash", "sound", "spatial" ] +}, { + "name" : "directions_subway", + "tags" : [ "automobile", "car", "cars", "direction", "directions", "maps", "public", "rail", "subway", "train", "transportation", "vehicle" ] +}, { + "name" : "reset_tv", + "tags" : [ "arrow", "device", "hardware", "monitor", "reset", "television", "tv" ] +}, { + "name" : "4k", + "tags" : [ "4000", "4K", "alphabet", "character", "digit", "display", "font", "letter", "number", "pixel", "pixels", "resolution", "symbol", "text", "type", "video" ] +}, { + "name" : "burst_mode", + "tags" : [ "burst", "image", "landscape", "mode", "mountain", "mountains", "multiple", "photo", "photography", "picture" ] +}, { + "name" : "chalet", + "tags" : [ "architecture", "chalet", "cottage", "estate", "home", "house", "maps", "place", "real", "residence", "residential", "stay", "traveling" ] +}, { + "name" : "battery_1_bar", + "tags" : [ "1", "bar", "battery", "cell", "charge", "mobile", "power" ] +}, { + "name" : "elderly_woman", + "tags" : [ "body", "cane", "elderly", "female", "gender", "girl", "human", "lady", "old", "people", "person", "senior", "social", "symbol", "woman", "women" ] +}, { + "name" : "headset_off", + "tags" : [ "accessory", "audio", "chat", "device", "disabled", "ear", "earphone", "enabled", "headphones", "headset", "listen", "mic", "music", "off", "on", "slash", "sound", "talk" ] +}, { + "name" : "swipe_vertical", + "tags" : [ "arrows", "direction", "finger", "hands", "hit", "navigation", "strike", "swing", "swpie", "take", "verticle" ] +}, { + "name" : "crib", + "tags" : [ "babies", "baby", "bassinet", "bed", "child", "children", "cradle", "crib", "infant", "kid", "newborn", "sleeping", "toddler" ] +}, { + "name" : "video_label", + "tags" : [ "label", "screen", "video", "window" ] +}, { + "name" : "fiber_smart_record", + "tags" : [ "circle", "dot", "fiber", "play", "record", "smart", "watch" ] +}, { + "name" : "brightness_auto", + "tags" : [ "A", "auto", "brightness", "control", "display", "level", "mobile", "monitor", "phone", "screen", "sun" ] +}, { + "name" : "margin", + "tags" : [ "design", "layout", "margin", "padding", "size", "square" ] +}, { + "name" : "punch_clock", + "tags" : [ "clock", "date", "punch", "schedule", "time", "timer", "timesheet" ] +}, { + "name" : "compass_calibration", + "tags" : [ "calibration", "compass", "connection", "internet", "location", "maps", "network", "refresh", "service", "signal", "wifi", "wireless" ] +}, { + "name" : "mosque", + "tags" : [ "islam", "islamic", "masjid", "muslim", "religion", "spiritual", "worship" ] +}, { + "name" : "medication_liquid", + "tags" : [ "+", "bottle", "doctor", "drug", "health", "hospital", "liquid", "medications", "medicine", "pharmacy", "spoon", "vessel" ] +}, { + "name" : "camera_roll", + "tags" : [ "camera", "film", "image", "library", "photo", "photography", "roll" ] +}, { + "name" : "pin_end", + "tags" : [ "action", "arrow", "dot", "end", "pin" ] +}, { + "name" : "dialer_sip", + "tags" : [ "alphabet", "call", "cell", "character", "contact", "device", "dialer", "font", "hardware", "initiation", "internet", "letter", "mobile", "over", "phone", "protocol", "routing", "session", "sip", "symbol", "telephone", "text", "type", "voice" ] +}, { + "name" : "oil_barrel", + "tags" : [ "barrel", "droplet", "gas", "gasoline", "nest", "oil", "water" ] +}, { + "name" : "disc_full", + "tags" : [ "!", "alert", "attention", "caution", "cd", "danger", "disc", "error", "exclamation", "full", "important", "mark", "music", "notification", "storage", "symbol", "warning" ] +}, { + "name" : "signal_cellular_connected_no_internet_4_bar", + "tags" : [ "!", "4", "alert", "attention", "bar", "caution", "cell", "cellular", "connected", "danger", "data", "error", "exclamation", "important", "internet", "mark", "mobile", "network", "no", "notification", "phone", "signal", "symbol", "warning", "wifi", "wireless" ] +}, { + "name" : "wind_power", + "tags" : [ "eco", "energy", "nest", "power", "wind", "windy" ] +}, { + "name" : "logo_dev", + "tags" : [ "dev", "dev.to", "logo" ] +}, { + "name" : "sledding", + "tags" : [ "athlete", "athletic", "body", "entertainment", "exercise", "hobby", "human", "people", "person", "sled", "sledding", "sledge", "snow", "social", "sports", "travel", "winter" ] +}, { + "name" : "invert_colors_off", + "tags" : [ "colors", "disabled", "drop", "droplet", "enabled", "hue", "invert", "inverted", "off", "offline", "on", "opacity", "palette", "slash", "tone", "water" ] +}, { + "name" : "wifi_lock", + "tags" : [ "cellular", "connection", "data", "internet", "lock", "locked", "mobile", "network", "password", "privacy", "private", "protection", "safety", "secure", "security", "service", "signal", "wifi", "wireless" ] +}, { + "name" : "noise_aware", + "tags" : [ "audio", "aware", "cancellation", "music", "noise", "note", "sound" ] +}, { + "name" : "face_3", + "tags" : [ "account", "emoji", "eyes", "face", "human", "lock", "log", "login", "logout", "people", "person", "profile", "recognition", "security", "social", "thumbnail", "unlock", "user" ] +}, { + "name" : "car_crash", + "tags" : [ "accident", "automobile", "car", "cars", "collision", "crash", "direction", "maps", "public", "transportation", "vehicle" ] +}, { + "name" : "comments_disabled", + "tags" : [ "bubble", "chat", "comment", "comments", "communicate", "disabled", "enabled", "feedback", "message", "off", "offline", "on", "slash", "speech" ] +}, { + "name" : "data_array", + "tags" : [ "array", "brackets", "code", "coder", "data", "parentheses" ] +}, { + "name" : "do_not_disturb_on_total_silence", + "tags" : [ "busy", "disturb", "do", "mute", "no", "not", "on total", "quiet", "silence" ] +}, { + "name" : "filter_b_and_w", + "tags" : [ "and", "b", "black", "contrast", "edit", "editing", "effect", "filter", "grayscale", "image", "images", "photography", "picture", "pictures", "settings", "w", "white" ] +}, { + "name" : "no_encryption_gmailerrorred", + "tags" : [ "disabled", "enabled", "encryption", "error", "gmail", "lock", "locked", "no", "off", "on", "slash" ] +}, { + "name" : "blur_linear", + "tags" : [ "blur", "dots", "edit", "editing", "effect", "enhance", "filter", "linear" ] +}, { + "name" : "view_cozy", + "tags" : [ "comfy", "cozy", "design", "format", "layout", "view", "web" ] +}, { + "name" : "wifi_calling", + "tags" : [ "call", "calling", "cell", "connect", "connection", "connectivity", "contact", "device", "hardware", "mobile", "phone", "signal", "telephone", "wifi", "wireless" ] +}, { + "name" : "electric_rickshaw", + "tags" : [ "automobile", "car", "cars", "electric", "india", "maps", "rickshaw", "transportation", "truck", "vehicle" ] +}, { + "name" : "rtt", + "tags" : [ "call", "real", "rrt", "text", "time" ] +}, { + "name" : "join_right", + "tags" : [ "circle", "command", "join", "matching", "overlap", "right", "sql", "values" ] +}, { + "name" : "crop_3_2", + "tags" : [ "2", "3", "adjust", "adjustments", "area", "by", "crop", "edit", "editing", "frame", "image", "images", "photo", "photos", "rectangle", "settings", "size", "square" ] +}, { + "name" : "crop_landscape", + "tags" : [ "adjust", "adjustments", "area", "crop", "edit", "editing", "frame", "image", "images", "landscape", "photo", "photos", "settings", "size" ] +}, { + "name" : "nearby_error", + "tags" : [ "!", "alert", "attention", "caution", "danger", "error", "exclamation", "important", "mark", "nearby", "notification", "symbol", "warning" ] +}, { + "name" : "airplanemode_inactive", + "tags" : [ "airplane", "airplanemode", "airport", "disabled", "enabled", "flight", "fly", "inactive", "maps", "mode", "off", "offline", "on", "slash", "transportation", "travel" ] +}, { + "name" : "airline_stops", + "tags" : [ "airline", "arrow", "destination", "direction", "layover", "location", "maps", "place", "stops", "transportation", "travel", "trip" ] +}, { + "name" : "bluetooth_audio", + "tags" : [ "audio", "bluetooth", "connect", "connection", "device", "music", "signal", "sound", "symbol" ] +}, { + "name" : "portable_wifi_off", + "tags" : [ "connection", "data", "disabled", "enabled", "internet", "network", "off", "offline", "on", "portable", "service", "signal", "slash", "wifi", "wireless" ] +}, { + "name" : "turn_right", + "tags" : [ "arrow", "arrows", "direction", "directions", "maps", "navigation", "path", "right", "route", "sign", "traffic", "turn" ] +}, { + "name" : "1x_mobiledata", + "tags" : [ "1x", "alphabet", "cellular", "character", "digit", "font", "letter", "mobile", "mobiledata", "network", "number", "phone", "signal", "speed", "symbol", "text", "type", "wifi" ] +}, { + "name" : "do_not_step", + "tags" : [ "boot", "disabled", "do", "enabled", "feet", "foot", "not", "off", "on", "shoe", "slash", "sneaker", "step", "steps" ] +}, { + "name" : "sensor_occupied", + "tags" : [ "body", "body response", "connection", "fitbit", "human", "network", "people", "person", "scan", "sensors", "signal", "smart body scan sensor", "wireless" ] +}, { + "name" : "directions_railway", + "tags" : [ "automobile", "car", "cars", "direction", "directions", "maps", "public", "railway", "train", "transportation", "vehicle" ] +}, { + "name" : "security_update_warning", + "tags" : [ "!", "Android", "OS", "alert", "attention", "caution", "danger", "device", "download", "error", "exclamation", "hardware", "iOS", "important", "mark", "mobile", "notification", "phone", "security", "symbol", "tablet", "update", "warning" ] +}, { + "name" : "pentagon", + "tags" : [ "five sides", "pentagon", "shape" ] +}, { + "name" : "wrap_text", + "tags" : [ "arrow writing", "doc", "edit", "editing", "editor", "sheet", "spreadsheet", "text", "type", "wrap", "write", "writing" ] +}, { + "name" : "no_meeting_room", + "tags" : [ "building", "disabled", "door", "doorway", "enabled", "entrance", "home", "house", "interior", "meeting", "no", "off", "office", "on", "open", "places", "room", "slash" ] +}, { + "name" : "sd_card_alert", + "tags" : [ "!", "alert", "attention", "camera", "card", "caution", "danger", "digital", "error", "exclamation", "important", "mark", "memory", "notification", "photos", "sd", "secure", "storage", "symbol", "warning" ] +}, { + "name" : "deselect", + "tags" : [ "all", "disabled", "enabled", "off", "on", "selection", "slash", "square", "tool" ] +}, { + "name" : "switch_camera", + "tags" : [ "arrow", "arrows", "camera", "photo", "photography", "picture", "switch" ] +}, { + "name" : "text_rotate_up", + "tags" : [ "A", "alphabet", "arrow", "character", "field", "font", "letter", "move", "rotate", "symbol", "text", "type", "up" ] +}, { + "name" : "sync_lock", + "tags" : [ "around", "arrow", "arrows", "lock", "locked", "password", "privacy", "private", "protection", "renew", "rotate", "safety", "secure", "security", "sync", "turn" ] +}, { + "name" : "switch_video", + "tags" : [ "arrow", "arrows", "camera", "photography", "switch", "video", "videos" ] +}, { + "name" : "border_clear", + "tags" : [ "border", "clear", "doc", "edit", "editing", "editor", "sheet", "spreadsheet", "stroke", "text", "type", "writing" ] +}, { + "name" : "repeat_one_on", + "tags" : [ "arrow", "arrows", "control", "controls", "digit", "media", "music", "number", "on", "one", "repeat", "symbol", "video" ] +}, { + "name" : "no_meals", + "tags" : [ "dining", "disabled", "eat", "enabled", "food", "fork", "knife", "meal", "meals", "no", "off", "on", "restaurant", "slash", "spoon", "utensils" ] +}, { + "name" : "align_vertical_top", + "tags" : [ "align", "alignment", "format", "layout", "lines", "paragraph", "rule", "rules", "style", "text", "top", "vertical" ] +}, { + "name" : "subscript", + "tags" : [ "2", "doc", "edit", "editing", "editor", "gmail", "novitas", "sheet", "spreadsheet", "style", "subscript", "symbol", "text", "writing", "x" ] +}, { + "name" : "font_download_off", + "tags" : [ "alphabet", "character", "disabled", "download", "enabled", "font", "letter", "off", "on", "slash", "square", "symbol", "text", "type" ] +}, { + "name" : "scoreboard", + "tags" : [ "board", "points", "score", "scoreboard", "sports" ] +}, { + "name" : "swipe_right_alt", + "tags" : [ "accept", "alt", "arrows", "direction", "finger", "hands", "hit", "navigation", "right", "strike", "swing", "swpie", "take" ] +}, { + "name" : "align_vertical_center", + "tags" : [ "align", "alignment", "center", "format", "layout", "lines", "paragraph", "rule", "rules", "style", "text", "vertical" ] +}, { + "name" : "electric_meter", + "tags" : [ "bolt", "electric", "energy", "fast", "lightning", "measure", "meter", "nest", "thunderbolt", "usage", "voltage", "volts" ] +}, { + "name" : "contact_emergency", + "tags" : [ "account", "avatar", "call", "cell", "contacts", "face", "human", "info", "information", "mobile", "people", "person", "phone", "profile", "user" ] +}, { + "name" : "signal_cellular_connected_no_internet_0_bar", + "tags" : [ "!", "0", "alert", "attention", "bar", "caution", "cell", "cellular", "connected", "danger", "data", "error", "exclamation", "important", "internet", "mark", "mobile", "network", "no", "notification", "phone", "signal", "symbol", "warning", "wifi", "wireless" ] +}, { + "name" : "sim_card_alert", + "tags" : [ "!", "alert", "attention", "camera", "card", "caution", "danger", "digital", "error", "exclamation", "important", "mark", "memory", "notification", "photos", "sd", "secure", "storage", "symbol", "warning" ] +}, { + "name" : "battery_2_bar", + "tags" : [ "2", "bar", "battery", "cell", "charge", "mobile", "power" ] +}, { + "name" : "text_rotation_angleup", + "tags" : [ "A", "alphabet", "angleup", "arrow", "character", "field", "font", "letter", "move", "rotate", "symbol", "text", "type" ] +}, { + "name" : "text_rotation_down", + "tags" : [ "A", "alphabet", "arrow", "character", "dow", "field", "font", "letter", "move", "rotate", "symbol", "text", "type" ] +}, { + "name" : "railway_alert", + "tags" : [ "!", "alert", "attention", "automobile", "bike", "car", "cars", "caution", "danger", "direction", "error", "exclamation", "important", "maps", "mark", "notification", "public", "railway", "scooter", "subway", "symbol", "train", "transportation", "vehicle", "vespa", "warning" ] +}, { + "name" : "escalator", + "tags" : [ "down", "escalator", "staircase", "up" ] +}, { + "name" : "electric_moped", + "tags" : [ "automobile", "bike", "car", "cars", "electric", "maps", "moped", "scooter", "transportation", "travel", "vehicle", "vespa" ] +}, { + "name" : "closed_caption_disabled", + "tags" : [ "accessible", "alphabet", "caption", "cc", "character", "closed", "decoder", "disabled", "enabled", "font", "language", "letter", "media", "movies", "off", "on", "slash", "subtitle", "subtitles", "symbol", "text", "tv", "type" ] +}, { + "name" : "filter_7", + "tags" : [ "7", "digit", "edit", "editing", "effect", "filter", "image", "images", "multiple", "number", "photography", "picture", "pictures", "settings", "stack", "symbol" ] +}, { + "name" : "heat_pump", + "tags" : [ "air conditioner", "cool", "energy", "furnance", "heat", "nest", "pump", "usage" ] +}, { + "name" : "dry", + "tags" : [ "air", "bathroom", "dry", "dryer", "fingers", "gesture", "hand", "wc" ] +}, { + "name" : "fork_right", + "tags" : [ "arrow", "arrows", "direction", "directions", "fork", "maps", "navigation", "path", "right", "route", "sign", "traffic" ] +}, { + "name" : "text_rotation_angledown", + "tags" : [ "A", "alphabet", "angledown", "arrow", "character", "field", "font", "letter", "move", "rotate", "symbol", "text", "type" ] +}, { + "name" : "do_not_disturb_off", + "tags" : [ "cancel", "close", "denied", "deny", "disabled", "disturb", "do", "enabled", "off", "on", "remove", "silence", "slash", "stop" ] +}, { + "name" : "screen_lock_portrait", + "tags" : [ "Android", "OS", "device", "hardware", "iOS", "lock", "mobile", "phone", "portrait", "rotate", "screen", "tablet" ] +}, { + "name" : "send_time_extension", + "tags" : [ "deliver", "dispatch", "envelop", "extension", "mail", "message", "schedule", "send", "time" ] +}, { + "name" : "keyboard_command_key", + "tags" : [ "button", "command key", "control", "keyboard" ] +}, { + "name" : "remove_from_queue", + "tags" : [ "desktop", "device", "display", "from", "hardware", "monitor", "queue", "remove", "screen", "steam" ] +}, { + "name" : "filter_4", + "tags" : [ "4", "digit", "edit", "editing", "effect", "filter", "image", "images", "multiple", "number", "photography", "picture", "pictures", "settings", "stack", "symbol" ] +}, { + "name" : "filter_9_plus", + "tags" : [ "+", "9", "digit", "edit", "editing", "effect", "filter", "image", "images", "multiple", "number", "photography", "picture", "pictures", "plus", "settings", "stack", "symbol" ] +}, { + "name" : "exposure_plus_2", + "tags" : [ "2", "add", "brightness", "contrast", "digit", "edit", "editing", "effect", "exposure", "image", "number", "photo", "photography", "plus", "settings", "symbol" ] +}, { + "name" : "surround_sound", + "tags" : [ "circle", "signal", "sound", "speaker", "surround", "system", "volumn", "wireless" ] +}, { + "name" : "airline_seat_individual_suite", + "tags" : [ "airline", "body", "business", "class", "first", "human", "individual", "people", "person", "rest", "seat", "sleep", "suite", "travel" ] +}, { + "name" : "home_max", + "tags" : [ "device", "gadget", "hardware", "home", "internet", "iot", "max", "nest", "smart", "things" ] +}, { + "name" : "phone_paused", + "tags" : [ "call", "cell", "contact", "device", "hardware", "mobile", "pause", "paused", "phone", "telephone" ] +}, { + "name" : "local_play", + "tags" : [ ] +}, { + "name" : "stroller", + "tags" : [ "baby", "care", "carriage", "child", "children", "infant", "kid", "newborn", "stroller", "toddler", "young" ] +}, { + "name" : "wifi_password", + "tags" : [ "(scan)", "[cellular", "connection", "data", "internet", "lock", "mobile]", "network", "password", "secure", "service", "signal", "wifi", "wireless" ] +}, { + "name" : "browse_gallery", + "tags" : [ "clock", "collection", "gallery", "library", "stack", "watch" ] +}, { + "name" : "system_security_update", + "tags" : [ "Android", "OS", "arrow", "cell", "device", "down", "hardware", "iOS", "mobile", "phone", "security", "system", "tablet", "update" ] +}, { + "name" : "person_2", + "tags" : [ "account", "face", "human", "people", "person", "profile", "user" ] +}, { + "name" : "screenshot_monitor", + "tags" : [ "Android", "OS", "chrome", "desktop", "device", "display", "hardware", "iOS", "mac", "monitor", "screen", "screengrab", "screenshot", "web", "window" ] +}, { + "name" : "wb_iridescent", + "tags" : [ "balance", "bright", "edit", "editing", "iridescent", "light", "lighting", "setting", "settings", "white", "wp" ] +}, { + "name" : "grid_off", + "tags" : [ "collage", "disabled", "enabled", "grid", "image", "layout", "off", "on", "slash", "view" ] +}, { + "name" : "system_security_update_warning", + "tags" : [ "!", "Android", "OS", "alert", "attention", "caution", "cell", "danger", "device", "error", "exclamation", "hardware", "iOS", "important", "mark", "mobile", "notification", "phone", "security", "symbol", "system", "tablet", "update", "warning" ] +}, { + "name" : "play_disabled", + "tags" : [ "control", "controls", "disabled", "enabled", "media", "music", "off", "on", "play", "slash", "video" ] +}, { + "name" : "php", + "tags" : [ "alphabet", "brackets", "character", "code", "css", "develop", "developer", "engineer", "engineering", "font", "html", "letter", "php", "platform", "symbol", "text", "type" ] +}, { + "name" : "phishing", + "tags" : [ "fish", "fishing", "fraud", "hook", "phishing", "scam" ] +}, { + "name" : "border_style", + "tags" : [ "border", "color", "doc", "edit", "editing", "editor", "sheet", "spreadsheet", "stroke", "style", "text", "type", "writing" ] +}, { + "name" : "motion_photos_paused", + "tags" : [ "animation", "circle", "motion", "pause", "paused", "photos", "video" ] +}, { + "name" : "headphones_battery", + "tags" : [ "accessory", "audio", "battery", "charging", "device", "ear", "earphone", "headphones", "headset", "listen", "music", "sound" ] +}, { + "name" : "monochrome_photos", + "tags" : [ "black", "camera", "image", "monochrome", "photo", "photography", "photos", "picture", "white" ] +}, { + "name" : "web_asset_off", + "tags" : [ "asset", "browser", "disabled", "enabled", "internet", "off", "on", "page", "screen", "slash", "web", "webpage", "website", "windows", "www" ] +}, { + "name" : "wifi_tethering_off", + "tags" : [ "cell", "cellular", "connection", "data", "disabled", "enabled", "internet", "mobile", "network", "off", "offline", "on", "phone", "scan", "service", "signal", "slash", "speed", "tethering", "wifi", "wireless" ] +}, { + "name" : "text_decrease", + "tags" : [ "-", "alphabet", "character", "decrease", "font", "letter", "minus", "remove", "resize", "subtract", "symbol", "text", "type" ] +}, { + "name" : "view_comfy_alt", + "tags" : [ "alt", "comfy", "cozy", "design", "format", "layout", "view", "web" ] +}, { + "name" : "photo_camera_back", + "tags" : [ "back", "camera", "image", "landscape", "mountain", "mountains", "photo", "photography", "picture", "rear" ] +}, { + "name" : "folder_off", + "tags" : [ "data", "disabled", "doc", "document", "drive", "enabled", "file", "folder", "folders", "off", "on", "online", "sheet", "slash", "slide", "storage" ] +}, { + "name" : "gas_meter", + "tags" : [ "droplet", "energy", "gas", "measure", "meter", "nest", "usage", "water" ] +}, { + "name" : "edgesensor_high", + "tags" : [ "Android", "OS", "cell", "device", "edge", "hardware", "high", "iOS", "mobile", "move", "phone", "sensitivity", "sensor", "tablet", "vibrate" ] +}, { + "name" : "filter_5", + "tags" : [ "5", "digit", "edit", "editing", "effect", "filter", "image", "images", "multiple", "number", "photography", "picture", "pictures", "settings", "stack", "symbol" ] +}, { + "name" : "stay_current_landscape", + "tags" : [ "Android", "OS", "current", "device", "hardware", "iOS", "landscape", "mobile", "phone", "stay", "tablet" ] +}, { + "name" : "sip", + "tags" : [ "alphabet", "call", "character", "dialer", "font", "initiation", "internet", "letter", "over", "phone", "protocol", "routing", "session", "sip", "symbol", "text", "type", "voice" ] +}, { + "name" : "power_input", + "tags" : [ "input", "lines", "power", "supply" ] +}, { + "name" : "smart_screen", + "tags" : [ "Android", "OS", "airplay", "cast", "cell", "connect", "device", "hardware", "iOS", "mobile", "phone", "screen", "screencast", "smart", "stream", "tablet", "video" ] +}, { + "name" : "mail_lock", + "tags" : [ "email", "envelop", "letter", "lock", "locked", "mail", "message", "password", "privacy", "private", "protection", "safety", "secure", "security", "send" ] +}, { + "name" : "dataset", + "tags" : [ ] +}, { + "name" : "nat", + "tags" : [ "communication", "nat" ] +}, { + "name" : "do_disturb_off", + "tags" : [ "cancel", "close", "denied", "deny", "disabled", "disturb", "do", "enabled", "off", "on", "remove", "silence", "slash", "stop" ] +}, { + "name" : "no_drinks", + "tags" : [ "alcohol", "beverage", "bottle", "cocktail", "drink", "drinks", "food", "liquor", "no", "wine" ] +}, { + "name" : "bike_scooter", + "tags" : [ "automobile", "bike", "car", "cars", "maps", "scooter", "transportation", "vehicle", "vespa" ] +}, { + "name" : "dock", + "tags" : [ "Android", "OS", "cell", "charging", "connector", "device", "dock", "hardware", "iOS", "mobile", "phone", "power", "station", "tablet" ] +}, { + "name" : "face_2", + "tags" : [ "account", "emoji", "eyes", "face", "human", "lock", "log", "login", "logout", "people", "person", "profile", "recognition", "security", "social", "thumbnail", "unlock", "user" ] +}, { + "name" : "face_retouching_off", + "tags" : [ "disabled", "edit", "editing", "effect", "emoji", "emotion", "enabled", "face", "faces", "image", "natural", "off", "on", "photo", "photography", "retouch", "retouching", "settings", "slash", "tag" ] +}, { + "name" : "auto_fix_off", + "tags" : [ "ai", "artificial", "auto", "automatic", "automation", "custom", "disabled", "edit", "enabled", "erase", "fix", "genai", "intelligence", "magic", "modify", "off", "on", "slash", "smart", "spark", "sparkle", "star", "wand" ] +}, { + "name" : "airline_seat_flat", + "tags" : [ "airline", "body", "business", "class", "first", "flat", "human", "people", "person", "rest", "seat", "sleep", "travel" ] +}, { + "name" : "phone_locked", + "tags" : [ "call", "cell", "contact", "device", "hardware", "lock", "locked", "mobile", "password", "phone", "privacy", "private", "protection", "safety", "secure", "security", "telephone" ] +}, { + "name" : "network_locked", + "tags" : [ "alert", "available", "cellular", "connection", "data", "error", "internet", "lock", "locked", "mobile", "network", "not", "privacy", "private", "protection", "restricted", "safety", "secure", "security", "service", "signal", "warning", "wifi", "wireless" ] +}, { + "name" : "padding", + "tags" : [ "design", "layout", "margin", "padding", "size", "square" ] +}, { + "name" : "browser_not_supported", + "tags" : [ "browser", "disabled", "enabled", "internet", "not", "off", "on", "page", "screen", "site", "slash", "supported", "web", "website", "www" ] +}, { + "name" : "border_outer", + "tags" : [ "border", "doc", "edit", "editing", "editor", "outer", "sheet", "spreadsheet", "stroke", "text", "type", "writing" ] +}, { + "name" : "exposure_neg_1", + "tags" : [ "1", "brightness", "contrast", "digit", "edit", "editing", "effect", "exposure", "image", "neg", "negative", "number", "photo", "photography", "settings", "symbol" ] +}, { + "name" : "view_compact_alt", + "tags" : [ "alt", "compact", "design", "format", "layout dense", "view", "web" ] +}, { + "name" : "pest_control_rodent", + "tags" : [ "control", "exterminator", "mice", "pest", "rodent" ] +}, { + "name" : "swipe_down_alt", + "tags" : [ "alt", "arrows", "direction", "disable", "down", "enable", "finger", "hands", "hit", "navigation", "strike", "swing", "swpie", "take" ] +}, { + "name" : "airlines", + "tags" : [ "airlines", "airplane", "airport", "flight", "plane", "transportation", "travel", "trip" ] +}, { + "name" : "turn_left", + "tags" : [ "arrow", "arrows", "direction", "directions", "left", "maps", "navigation", "path", "route", "sign", "traffic", "turn" ] +}, { + "name" : "sd", + "tags" : [ "alphabet", "camera", "card", "character", "data", "device", "digital", "drive", "flash", "font", "image", "letter", "memory", "photo", "sd", "secure", "symbol", "text", "type" ] +}, { + "name" : "near_me_disabled", + "tags" : [ "destination", "direction", "disabled", "enabled", "location", "maps", "me", "navigation", "near", "off", "on", "pin", "place", "point", "slash" ] +}, { + "name" : "face_4", + "tags" : [ "account", "emoji", "eyes", "face", "human", "lock", "log", "login", "logout", "people", "person", "profile", "recognition", "security", "social", "thumbnail", "unlock", "user" ] +}, { + "name" : "stay_primary_landscape", + "tags" : [ "Android", "OS", "current", "device", "hardware", "iOS", "landscape", "mobile", "phone", "primary", "stay", "tablet" ] +}, { + "name" : "4g_plus_mobiledata", + "tags" : [ "4g", "alphabet", "cellular", "character", "digit", "font", "letter", "mobile", "mobiledata", "network", "number", "phone", "plus", "signal", "speed", "symbol", "text", "type", "wifi" ] +}, { + "name" : "snowmobile", + "tags" : [ "automobile", "car", "direction", "skimobile", "snow", "snowmobile", "social", "sports", "transportation", "travel", "vehicle", "winter" ] +}, { + "name" : "sign_language", + "tags" : [ "communication", "deaf", "fingers", "gesture", "hand", "language", "sign" ] +}, { + "name" : "network_ping", + "tags" : [ "alert", "available", "cellular", "connection", "data", "internet", "ip", "mobile", "network", "ping", "service", "signal", "wifi", "wireless" ] +}, { + "name" : "signal_cellular_off", + "tags" : [ "cell", "cellular", "data", "disabled", "enabled", "internet", "mobile", "network", "off", "offline", "on", "phone", "signal", "slash", "wifi", "wireless" ] +}, { + "name" : "signal_cellular_nodata", + "tags" : [ "cell", "cellular", "data", "internet", "mobile", "network", "no", "nodata", "offline", "phone", "quit", "signal", "wifi", "wireless", "x" ] +}, { + "name" : "no_sim", + "tags" : [ "camera", "card", "device", "eject", "insert", "memory", "no", "phone", "sim", "storage" ] +}, { + "name" : "signal_wifi_4_bar_lock", + "tags" : [ "4", "bar", "cell", "cellular", "data", "internet", "lock", "locked", "mobile", "network", "password", "phone", "privacy", "private", "protection", "safety", "secure", "security", "signal", "wifi", "wireless" ] +}, { + "name" : "missed_video_call", + "tags" : [ "arrow", "call", "camera", "film", "filming", "hardware", "image", "missed", "motion", "picture", "record", "video", "videography" ] +}, { + "name" : "lte_mobiledata", + "tags" : [ "alphabet", "character", "data", "font", "internet", "letter", "lte", "mobile", "network", "speed", "symbol", "text", "type", "wifi", "wireless" ] +}, { + "name" : "earbuds_battery", + "tags" : [ "accessory", "audio", "battery", "charging", "earbuds", "earphone", "headphone", "listen", "music", "sound" ] +}, { + "name" : "panorama_photosphere", + "tags" : [ "angle", "horizontal", "image", "panorama", "photo", "photography", "photosphere", "picture", "wide" ] +}, { + "name" : "no_crash", + "tags" : [ "accident", "auto", "automobile", "car", "cars", "check", "collision", "confirm", "correct", "crash", "direction", "done", "enter", "maps", "mark", "no", "ok", "okay", "select", "tick", "transportation", "vehicle", "yes" ] +}, { + "name" : "add_alarm", + "tags" : [ ] +}, { + "name" : "directions_transit_filled", + "tags" : [ "automobile", "car", "cars", "direction", "directions", "filled", "maps", "public", "rail", "subway", "train", "transit", "transportation", "vehicle" ] +}, { + "name" : "u_turn_left", + "tags" : [ "arrow", "arrows", "direction", "directions", "left", "maps", "navigation", "path", "route", "sign", "traffic", "u-turn" ] +}, { + "name" : "line_axis", + "tags" : [ "axis", "dash", "horizontal", "line", "stroke", "vertical" ] +}, { + "name" : "density_large", + "tags" : [ "density", "horizontal", "large", "lines", "rule", "rules" ] +}, { + "name" : "location_disabled", + "tags" : [ "destination", "direction", "disabled", "enabled", "location", "maps", "off", "on", "pin", "place", "pointer", "slash", "stop", "tracking" ] +}, { + "name" : "bluetooth_drive", + "tags" : [ "automobile", "bluetooth", "car", "cars", "cast", "connect", "connection", "device", "drive", "maps", "paring", "streaming", "symbol", "transportation", "travel", "vehicle", "wireless" ] +}, { + "name" : "30fps", + "tags" : [ "30fps", "alphabet", "camera", "character", "digit", "font", "fps", "frames", "letter", "number", "symbol", "text", "type", "video" ] +}, { + "name" : "no_luggage", + "tags" : [ "bag", "baggage", "carry", "disabled", "enabled", "luggage", "no", "off", "on", "slash", "suitcase", "travel" ] +}, { + "name" : "leak_remove", + "tags" : [ "connection", "data", "disabled", "enabled", "leak", "link", "network", "off", "offline", "on", "remove", "service", "signals", "slash", "synce", "wireless" ] +}, { + "name" : "filter_8", + "tags" : [ "8", "digit", "edit", "editing", "effect", "filter", "image", "images", "multiple", "number", "photography", "picture", "pictures", "settings", "stack", "symbol" ] +}, { + "name" : "mobile_off", + "tags" : [ "Android", "OS", "cell", "device", "disabled", "enabled", "hardware", "iOS", "mobile", "off", "on", "phone", "silence", "slash", "tablet" ] +}, { + "name" : "key_off", + "tags" : [ "disabled", "enabled", "key", "lock", "off", "offline", "on", "password", "slash", "unlock" ] +}, { + "name" : "signal_cellular_null", + "tags" : [ "cell", "cellular", "data", "internet", "mobile", "network", "null", "phone", "signal", "wifi", "wireless" ] +}, { + "name" : "phonelink_off", + "tags" : [ "Android", "OS", "chrome", "computer", "connect", "desktop", "device", "disabled", "enabled", "hardware", "iOS", "link", "mac", "mobile", "off", "on", "phone", "phonelink", "slash", "sync", "tablet", "web", "windows" ] +}, { + "name" : "filter_9", + "tags" : [ "9", "digit", "edit", "editing", "effect", "filter", "image", "images", "multiple", "number", "photography", "picture", "pictures", "settings", "stack", "symbol" ] +}, { + "name" : "home_mini", + "tags" : [ "Internet", "device", "gadget", "hardware", "home", "iot", "mini", "nest", "smart", "things" ] +}, { + "name" : "on_device_training", + "tags" : [ "arrow", "bulb", "call", "cell", "contact", "device", "hardware", "idea", "inprogress", "light", "load", "loading", "mobile", "model", "phone", "refresh", "renew", "restore", "reverse", "rotate", "telephone", "training" ] +}, { + "name" : "egg_alt", + "tags" : [ "breakfast", "brunch", "egg", "food" ] +}, { + "name" : "media_bluetooth_on", + "tags" : [ "bluetooth", "connect", "connection", "connectivity", "device", "disabled", "enabled", "media", "music", "note", "off", "on", "online", "paring", "signal", "slash", "symbol", "wireless" ] +}, { + "name" : "10k", + "tags" : [ "10000", "10K", "alphabet", "character", "digit", "display", "font", "letter", "number", "pixel", "pixels", "resolution", "symbol", "text", "type", "video" ] +}, { + "name" : "video_stable", + "tags" : [ "film", "filming", "recording", "setting", "stability", "stable", "taping", "video" ] +}, { + "name" : "add_home", + "tags" : [ ] +}, { + "name" : "no_transfer", + "tags" : [ "automobile", "bus", "car", "cars", "direction", "disabled", "enabled", "maps", "no", "off", "on", "public", "slash", "transfer", "transportation", "vehicle" ] +}, { + "name" : "timer_10", + "tags" : [ "10", "digits", "duration", "number", "numbers", "seconds", "time", "timer" ] +}, { + "name" : "directions_subway_filled", + "tags" : [ "automobile", "car", "cars", "direction", "directions", "filled", "maps", "public", "rail", "subway", "train", "transportation", "vehicle" ] +}, { + "name" : "wb_shade", + "tags" : [ "balance", "house", "light", "lighting", "shade", "wb", "white" ] +}, { + "name" : "swipe_left_alt", + "tags" : [ "alt", "arrow", "arrows", "finger", "hand", "hit", "left", "navigation", "reject", "strike", "swing", "swipe", "take" ] +}, { + "name" : "filter_6", + "tags" : [ "6", "digit", "edit", "editing", "effect", "filter", "image", "images", "multiple", "number", "photography", "picture", "pictures", "settings", "stack", "symbol" ] +}, { + "name" : "cyclone", + "tags" : [ "crisis", "disaster", "natural", "rain", "storm", "weather", "wind", "winds" ] +}, { + "name" : "network_wifi_1_bar", + "tags" : [ ] +}, { + "name" : "directions_railway_filled", + "tags" : [ "automobile", "car", "cars", "direction", "directions", "filled", "maps", "public", "railway", "train", "transportation", "vehicle" ] +}, { + "name" : "wifi_find", + "tags" : [ "(scan)", "[cellular", "connection", "data", "detect", "discover", "find", "internet", "look", "magnifying glass", "mobile]", "network", "notice", "search", "service", "signal", "wifi", "wireless" ] +}, { + "name" : "blur_off", + "tags" : [ "blur", "disabled", "dots", "edit", "editing", "effect", "enabled", "enhance", "off", "on", "slash" ] +}, { + "name" : "motion_photos_off", + "tags" : [ "animation", "circle", "disabled", "enabled", "motion", "off", "on", "photos", "slash", "video" ] +}, { + "name" : "lyrics", + "tags" : [ "audio", "bubble", "chat", "comment", "communicate", "feedback", "key", "lyrics", "message", "music", "note", "song", "sound", "speech", "track" ] +}, { + "name" : "raw_on", + "tags" : [ "alphabet", "character", "disabled", "enabled", "font", "image", "letter", "off", "on", "original", "photo", "photography", "raw", "slash", "symbol", "text", "type" ] +}, { + "name" : "flight_class", + "tags" : [ "airplane", "business", "class", "first", "flight", "plane", "seat", "transportation", "travel", "trip", "window" ] +}, { + "name" : "insert_page_break", + "tags" : [ "break", "doc", "document", "file", "page", "paper" ] +}, { + "name" : "rsvp", + "tags" : [ "alphabet", "character", "font", "invitation", "invite", "letter", "plaît", "respond", "rsvp", "répondez", "sil", "symbol", "text", "type", "vous" ] +}, { + "name" : "tire_repair", + "tags" : [ "auto", "automobile", "car", "cars", "gauge", "mechanic", "pressure", "repair", "tire", "vehicle" ] +}, { + "name" : "swipe_up_alt", + "tags" : [ "alt", "arrows", "direction", "disable", "enable", "finger", "hands", "hit", "navigation", "strike", "swing", "swpie", "take", "up" ] +}, { + "name" : "3g_mobiledata", + "tags" : [ "3g", "alphabet", "cellular", "character", "digit", "font", "letter", "mobile", "mobiledata", "network", "number", "phone", "signal", "speed", "symbol", "text", "type", "wifi" ] +}, { + "name" : "tv_off", + "tags" : [ "Android", "OS", "chrome", "desktop", "device", "disabled", "enabled", "hardware", "iOS", "mac", "monitor", "off", "on", "slash", "television", "tv", "web", "window" ] +}, { + "name" : "hdr_on", + "tags" : [ "add", "alphabet", "character", "dynamic", "enhance", "font", "hdr", "high", "letter", "on", "plus", "range", "select", "symbol", "text", "type" ] +}, { + "name" : "add_home_work", + "tags" : [ ] +}, { + "name" : "motion_photos_pause", + "tags" : [ "animation", "circle", "motion", "pause", "paused", "photos", "video" ] +}, { + "name" : "edgesensor_low", + "tags" : [ "Android", "cell", "device", "edge", "hardware", "iOS", "low", "mobile", "move", "phone", "sensitivity", "sensor", "tablet", "vibrate" ] +}, { + "name" : "grid_goldenratio", + "tags" : [ "golden", "goldenratio", "grid", "layout", "lines", "ratio", "space" ] +}, { + "name" : "network_wifi_3_bar", + "tags" : [ ] +}, { + "name" : "temple_buddhist", + "tags" : [ "buddha", "buddhism", "buddhist", "monastery", "religion", "spiritual", "temple", "worship" ] +}, { + "name" : "airline_seat_flat_angled", + "tags" : [ "airline", "angled", "body", "business", "class", "first", "flat", "human", "people", "person", "rest", "seat", "sleep", "travel" ] +}, { + "name" : "fort", + "tags" : [ "castle", "fort", "fortress", "mansion", "palace" ] +}, { + "name" : "spatial_tracking", + "tags" : [ "audio", "disabled", "enabled", "music", "note", "off", "offline", "on", "slash", "sound", "spatial", "tracking" ] +}, { + "name" : "screen_lock_rotation", + "tags" : [ "Android", "OS", "arrow", "device", "hardware", "iOS", "lock", "mobile", "phone", "rotate", "rotation", "screen", "tablet", "turn" ] +}, { + "name" : "fiber_pin", + "tags" : [ "alphabet", "character", "fiber", "font", "letter", "network", "pin", "symbol", "text", "type" ] +}, { + "name" : "phone_bluetooth_speaker", + "tags" : [ "bluetooth", "call", "cell", "connect", "connection", "connectivity", "contact", "device", "hardware", "mobile", "phone", "signal", "speaker", "symbol", "telephone", "wireless" ] +}, { + "name" : "vignette", + "tags" : [ "border", "edit", "editing", "filter", "gradient", "image", "photo", "photography", "setting", "vignette" ] +}, { + "name" : "panorama_horizontal", + "tags" : [ "angle", "horizontal", "image", "panorama", "photo", "photography", "picture", "wide" ] +}, { + "name" : "propane_tank", + "tags" : [ "bbq", "gas", "grill", "nest", "propane", "tank" ] +}, { + "name" : "kebab_dining", + "tags" : [ "dining", "dinner", "food", "kebab", "meal", "meat", "skewer" ] +}, { + "name" : "developer_board_off", + "tags" : [ "board", "chip", "computer", "developer", "development", "disabled", "enabled", "hardware", "microchip", "off", "on", "processor", "slash" ] +}, { + "name" : "adf_scanner", + "tags" : [ "adf", "document", "feeder", "machine", "office", "scan", "scanner" ] +}, { + "name" : "no_cell", + "tags" : [ "Android", "OS", "cell", "device", "disabled", "enabled", "hardware", "iOS", "mobile", "no", "off", "on", "phone", "slash", "tablet" ] +}, { + "name" : "dirty_lens", + "tags" : [ "camera", "dirty", "lens", "photo", "photography", "picture", "splat" ] +}, { + "name" : "usb_off", + "tags" : [ "cable", "connection", "device", "off", "usb", "wire" ] +}, { + "name" : "image_aspect_ratio", + "tags" : [ "aspect", "image", "photo", "photography", "picture", "ratio", "rectangle", "square" ] +}, { + "name" : "30fps_select", + "tags" : [ "30", "camera", "digits", "fps", "frame", "frequency", "image", "numbers", "per", "rate", "second", "seconds", "select", "video" ] +}, { + "name" : "60fps", + "tags" : [ "60fps", "camera", "digit", "fps", "frames", "number", "symbol", "video" ] +}, { + "name" : "screen_lock_landscape", + "tags" : [ "Android", "OS", "device", "hardware", "iOS", "landscape", "lock", "mobile", "phone", "rotate", "screen", "tablet" ] +}, { + "name" : "lte_plus_mobiledata", + "tags" : [ "+", "alphabet", "character", "data", "font", "internet", "letter", "lte", "mobile", "network", "plus", "speed", "symbol", "text", "type", "wifi", "wireless" ] +}, { + "name" : "piano_off", + "tags" : [ "disabled", "enabled", "instrument", "keyboard", "keys", "music", "musical", "off", "on", "piano", "slash", "social" ] +}, { + "name" : "unfold_more_double", + "tags" : [ "arrow", "arrows", "chevron", "collapse", "direction", "double", "down", "expand", "expandable", "list", "more", "navigation", "unfold" ] +}, { + "name" : "deblur", + "tags" : [ "adjust", "deblur", "edit", "editing", "enhance", "face", "image", "lines", "photo", "photography", "sharpen" ] +}, { + "name" : "person_4", + "tags" : [ "account", "face", "human", "people", "person", "profile", "user" ] +}, { + "name" : "spatial_audio", + "tags" : [ "audio", "music", "note", "sound", "spatial" ] +}, { + "name" : "camera_rear", + "tags" : [ "camera", "front", "lens", "mobile", "phone", "photo", "photography", "picture", "portrait", "rear", "selfie" ] +}, { + "name" : "timer_10_select", + "tags" : [ "10", "alphabet", "camera", "character", "digit", "font", "letter", "number", "seconds", "select", "symbol", "text", "timer", "type" ] +}, { + "name" : "face_5", + "tags" : [ "account", "emoji", "eyes", "face", "human", "lock", "log", "login", "logout", "people", "person", "profile", "recognition", "security", "social", "thumbnail", "unlock", "user" ] +}, { + "name" : "minor_crash", + "tags" : [ "accident", "auto", "automobile", "car", "cars", "collision", "directions", "maps", "public", "transportation", "vehicle" ] +}, { + "name" : "sos", + "tags" : [ "font", "help", "letters", "save", "sos", "text", "type" ] +}, { + "name" : "videogame_asset_off", + "tags" : [ "asset", "console", "controller", "device", "disabled", "enabled", "game", "gamepad", "gaming", "off", "on", "playstation", "slash", "video", "videogame" ] +}, { + "name" : "flood", + "tags" : [ "crisis", "disaster", "natural", "rain", "storm", "weather" ] +}, { + "name" : "60fps_select", + "tags" : [ "60", "camera", "digits", "fps", "frame", "frequency", "numbers", "per", "rate", "second", "seconds", "select", "video" ] +}, { + "name" : "timer_3", + "tags" : [ "3", "digits", "duration", "number", "numbers", "seconds", "time", "timer" ] +}, { + "name" : "vpn_key_off", + "tags" : [ "code", "disabled", "enabled", "key", "lock", "network", "off", "offline", "on", "passcode", "password", "slash", "unlock", "vpn" ] +}, { + "name" : "directions_off", + "tags" : [ "arrow", "directions", "disabled", "enabled", "maps", "off", "on", "right", "route", "sign", "slash", "traffic" ] +}, { + "name" : "emergency_share", + "tags" : [ "alert", "attention", "caution", "danger", "emergency", "important", "notification", "share", "warning" ] +}, { + "name" : "panorama_wide_angle_select", + "tags" : [ "angle", "image", "panorama", "photo", "photography", "picture", "select", "wide" ] +}, { + "name" : "airline_seat_legroom_normal", + "tags" : [ "airline", "body", "feet", "human", "leg", "legroom", "normal", "people", "person", "seat", "sitting", "space", "travel" ] +}, { + "name" : "fiber_dvr", + "tags" : [ "alphabet", "character", "digital", "dvr", "electronics", "fiber", "font", "letter", "network", "record", "recorder", "symbol", "text", "tv", "type", "video" ] +}, { + "name" : "person_3", + "tags" : [ "account", "face", "human", "people", "person", "profile", "user" ] +}, { + "name" : "scuba_diving", + "tags" : [ "diving", "entertainment", "exercise", "hobby", "scuba", "social", "swim", "swimming" ] +}, { + "name" : "signal_cellular_no_sim", + "tags" : [ "camera", "card", "cellular", "chip", "device", "disabled", "enabled", "memory", "no", "off", "offline", "on", "phone", "signal", "sim", "slash", "storage" ] +}, { + "name" : "24mp", + "tags" : [ "24", "camera", "digits", "font", "image", "letters", "megapixel", "megapixels", "mp", "numbers", "pixel", "pixels", "quality", "resolution", "symbol", "text", "type" ] +}, { + "name" : "exposure_neg_2", + "tags" : [ "2", "brightness", "contrast", "digit", "edit", "editing", "effect", "exposure", "image", "neg", "negative", "number", "photo", "photography", "settings", "symbol" ] +}, { + "name" : "network_wifi_2_bar", + "tags" : [ ] +}, { + "name" : "wifi_2_bar", + "tags" : [ "2", "bar", "cell", "cellular", "connection", "data", "internet", "mobile", "network", "phone", "scan", "service", "signal", "wifi", "wireless" ] +}, { + "name" : "u_turn_right", + "tags" : [ "arrow", "arrows", "direction", "directions", "maps", "navigation", "path", "right", "route", "sign", "traffic", "u-turn" ] +}, { + "name" : "currency_yuan", + "tags" : [ "bill", "card", "cash", "coin", "commerce", "cost", "credit", "currency", "dollars", "finance", "money", "online", "pay", "payment", "price", "shopping", "symbol", "yuan" ] +}, { + "name" : "currency_lira", + "tags" : [ "bill", "card", "cash", "coin", "commerce", "cost", "credit", "currency", "dollars", "finance", "lira", "money", "online", "pay", "payment", "price", "shopping", "symbol" ] +}, { + "name" : "no_flash", + "tags" : [ "bolt", "camera", "disabled", "enabled", "flash", "image", "lightning", "no", "off", "on", "photo", "photography", "picture", "slash", "thunderbolt" ] +}, { + "name" : "temple_hindu", + "tags" : [ "hindu", "hinduism", "hindus", "mandir", "religion", "spiritual", "temple", "worship" ] +}, { + "name" : "mode_fan_off", + "tags" : [ "air conditioner", "cool", "disabled", "enabled", "fan", "nest", "off", "on", "slash" ] +}, { + "name" : "airline_seat_legroom_extra", + "tags" : [ "airline", "body", "extra", "feet", "human", "leg", "legroom", "people", "person", "seat", "sitting", "space", "travel" ] +}, { + "name" : "4k_plus", + "tags" : [ "+", "4000", "4K", "alphabet", "character", "digit", "display", "font", "letter", "number", "pixel", "pixels", "plus", "resolution", "symbol", "text", "type", "video" ] +}, { + "name" : "border_inner", + "tags" : [ "border", "doc", "edit", "editing", "editor", "inner", "sheet", "spreadsheet", "stroke", "text", "type", "writing" ] +}, { + "name" : "wifi_tethering_error", + "tags" : [ "!", "alert", "attention", "caution", "cell", "cellular", "connection", "danger", "data", "error", "exclamation", "important", "internet", "mark", "mobile", "network", "notification", "phone", "rounded", "scan", "service", "signal", "speed", "symbol", "tethering", "warning", "wifi", "wireless" ] +}, { + "name" : "airline_seat_legroom_reduced", + "tags" : [ "airline", "body", "feet", "human", "leg", "legroom", "people", "person", "reduced", "seat", "sitting", "space", "travel" ] +}, { + "name" : "synagogue", + "tags" : [ "jew", "jewish", "religion", "shul", "spiritual", "temple", "worship" ] +}, { + "name" : "border_left", + "tags" : [ "border", "doc", "edit", "editing", "editor", "left", "sheet", "spreadsheet", "stroke", "text", "type", "writing" ] +}, { + "name" : "autofps_select", + "tags" : [ "A", "alphabet", "auto", "character", "font", "fps", "frame", "frequency", "letter", "per", "rate", "second", "seconds", "select", "symbol", "text", "type" ] +}, { + "name" : "signal_cellular_alt_2_bar", + "tags" : [ "2", "bar", "cell", "cellular", "data", "internet", "mobile", "network", "phone", "signal", "speed", "wifi", "wireless" ] +}, { + "name" : "g_mobiledata", + "tags" : [ "alphabet", "character", "data", "font", "g", "letter", "mobile", "network", "service", "symbol", "text", "type" ] +}, { + "name" : "1k", + "tags" : [ "1000", "1K", "alphabet", "character", "digit", "display", "font", "letter", "number", "pixel", "pixels", "resolution", "symbol", "text", "type", "video" ] +}, { + "name" : "format_textdirection_l_to_r", + "tags" : [ "align", "alignment", "doc", "edit", "editing", "editor", "format", "ltr", "sheet", "spreadsheet", "text", "textdirection", "type", "writing" ] +}, { + "name" : "border_bottom", + "tags" : [ "border", "bottom", "doc", "edit", "editing", "editor", "sheet", "spreadsheet", "stroke", "text", "type", "writing" ] +}, { + "name" : "fork_left", + "tags" : [ "arrow", "arrows", "direction", "directions", "fork", "left", "maps", "navigation", "path", "route", "sign", "traffic" ] +}, { + "name" : "severe_cold", + "tags" : [ "!", "alert", "attention", "caution", "climate", "cold", "crisis", "danger", "disaster", "error", "exclamation", "important", "notification", "severe", "snow", "snowflake", "warning", "weather", "winter" ] +}, { + "name" : "tsunami", + "tags" : [ "crisis", "disaster", "flood", "rain", "storm", "tsunami", "weather" ] +}, { + "name" : "signal_cellular_alt_1_bar", + "tags" : [ "1", "bar", "cell", "cellular", "data", "internet", "mobile", "network", "phone", "signal", "speed", "wifi", "wireless" ] +}, { + "name" : "border_vertical", + "tags" : [ "border", "doc", "edit", "editing", "editor", "sheet", "spreadsheet", "stroke", "text", "type", "vertical", "writing" ] +}, { + "name" : "turn_sharp_right", + "tags" : [ "arrow", "arrows", "direction", "directions", "maps", "navigation", "path", "right", "route", "sharp", "sign", "traffic", "turn" ] +}, { + "name" : "no_backpack", + "tags" : [ "accessory", "backpack", "bag", "bookbag", "knapsack", "no", "pack", "travel" ] +}, { + "name" : "remove_road", + "tags" : [ "-", "cancel", "close", "destination", "direction", "exit", "highway", "maps", "minus", "new", "no", "remove", "road", "stop", "street", "symbol", "traffic", "x" ] +}, { + "name" : "timer_3_select", + "tags" : [ "3", "alphabet", "camera", "character", "digit", "font", "letter", "number", "seconds", "select", "symbol", "text", "timer", "type" ] +}, { + "name" : "roller_skating", + "tags" : [ "athlete", "athletic", "entertainment", "exercise", "hobby", "roller", "shoe", "skate", "skates", "skating", "social", "sports", "travel" ] +}, { + "name" : "panorama_horizontal_select", + "tags" : [ "angle", "horizontal", "image", "panorama", "photo", "photography", "picture", "select", "wide" ] +}, { + "name" : "border_horizontal", + "tags" : [ "border", "doc", "edit", "editing", "editor", "horizontal", "sheet", "spreadsheet", "stroke", "text", "type", "writing" ] +}, { + "name" : "2k", + "tags" : [ "2000", "2K", "alphabet", "character", "digit", "display", "font", "letter", "number", "pixel", "pixels", "resolution", "symbol", "text", "type", "video" ] +}, { + "name" : "wifi_1_bar", + "tags" : [ "1", "bar", "cell", "cellular", "connection", "data", "internet", "mobile", "network", "phone", "scan", "service", "signal", "wifi", "wireless" ] +}, { + "name" : "format_textdirection_r_to_l", + "tags" : [ "align", "alignment", "doc", "edit", "editing", "editor", "format", "rtl", "sheet", "spreadsheet", "text", "textdirection", "type", "writing" ] +}, { + "name" : "wifi_channel", + "tags" : [ "(scan)", "[cellular", "channel", "connection", "data", "internet", "mobile]", "network", "service", "signal", "wifi", "wireless" ] +}, { + "name" : "roundabout_right", + "tags" : [ "arrow", "arrows", "direction", "directions", "maps", "navigation", "path", "right", "roundabout", "route", "sign", "traffic" ] +}, { + "name" : "wb_auto", + "tags" : [ "A", "W", "alphabet", "auto", "automatic", "balance", "character", "edit", "editing", "font", "image", "letter", "photo", "photography", "symbol", "text", "type", "white", "wp" ] +}, { + "name" : "panorama_photosphere_select", + "tags" : [ "angle", "horizontal", "image", "panorama", "photo", "photography", "photosphere", "picture", "select", "wide" ] +}, { + "name" : "panorama_wide_angle", + "tags" : [ "angle", "image", "panorama", "photo", "photography", "picture", "wide" ] +}, { + "name" : "hdr_plus", + "tags" : [ "+", "add", "alphabet", "character", "circle", "dynamic", "enhance", "font", "hdr", "high", "letter", "plus", "range", "select", "symbol", "text", "type" ] +}, { + "name" : "panorama_vertical_select", + "tags" : [ "angle", "image", "panorama", "photo", "photography", "picture", "select", "vertical", "wide" ] +}, { + "name" : "border_top", + "tags" : [ "border", "doc", "edit", "editing", "editor", "sheet", "spreadsheet", "stroke", "text", "top", "type", "writing" ] +}, { + "name" : "mic_external_off", + "tags" : [ "audio", "disabled", "enabled", "external", "mic", "microphone", "off", "on", "slash", "sound", "voice" ] +}, { + "name" : "width_full", + "tags" : [ ] +}, { + "name" : "h_mobiledata", + "tags" : [ "alphabet", "character", "data", "font", "h", "letter", "mobile", "network", "service", "symbol", "text", "type" ] +}, { + "name" : "roller_shades", + "tags" : [ "blinds", "cover", "curtains", "nest", "open", "roller", "shade", "shutter", "sunshade" ] +}, { + "name" : "no_stroller", + "tags" : [ "baby", "care", "carriage", "child", "children", "disabled", "enabled", "infant", "kid", "newborn", "no", "off", "on", "parents", "slash", "stroller", "toddler", "young" ] +}, { + "name" : "tornado", + "tags" : [ "crisis", "disaster", "natural", "rain", "storm", "tornado", "weather", "wind" ] +}, { + "name" : "keyboard_control_key", + "tags" : [ "control key", "keyboard" ] +}, { + "name" : "turn_slight_right", + "tags" : [ "arrow", "arrows", "direction", "directions", "maps", "navigation", "path", "right", "route", "sharp", "sign", "slight", "traffic", "turn" ] +}, { + "name" : "border_right", + "tags" : [ "border", "doc", "edit", "editing", "editor", "right", "sheet", "spreadsheet", "stroke", "text", "type", "writing" ] +}, { + "name" : "1k_plus", + "tags" : [ "+", "1000", "1K", "alphabet", "character", "digit", "display", "font", "letter", "number", "pixel", "pixels", "plus", "resolution", "symbol", "text", "type", "video" ] +}, { + "name" : "turn_slight_left", + "tags" : [ "arrow", "arrows", "direction", "directions", "maps", "navigation", "path", "right", "route", "sign", "slight", "traffic", "turn" ] +}, { + "name" : "screen_rotation_alt", + "tags" : [ "Android", "OS", "arrow", "device", "hardware", "iOS", "mobile", "phone", "rotate", "rotation", "screen", "tablet", "turn" ] +}, { + "name" : "dataset_linked", + "tags" : [ ] +}, { + "name" : "unfold_less_double", + "tags" : [ "arrow", "arrows", "chevron", "collapse", "direction", "double", "expand", "expandable", "inward", "less", "list", "navigation", "unfold", "up" ] +}, { + "name" : "8k", + "tags" : [ "8000", "8K", "alphabet", "character", "digit", "display", "font", "letter", "number", "pixel", "pixels", "resolution", "symbol", "text", "type", "video" ] +}, { + "name" : "landslide", + "tags" : [ "crisis", "disaster", "natural", "rain", "storm", "weather" ] +}, { + "name" : "media_bluetooth_off", + "tags" : [ "bluetooth", "connect", "connection", "connectivity", "device", "disabled", "enabled", "media", "music", "note", "off", "offline", "on", "paring", "signal", "slash", "symbol", "wireless" ] +}, { + "name" : "fire_truck", + "tags" : [ ] +}, { + "name" : "e_mobiledata", + "tags" : [ "alphabet", "data", "e", "font", "letter", "mobile", "mobiledata", "text", "type" ] +}, { + "name" : "panorama_vertical", + "tags" : [ "angle", "image", "panorama", "photo", "photography", "picture", "vertical", "wide" ] +}, { + "name" : "r_mobiledata", + "tags" : [ "alphabet", "character", "data", "font", "letter", "mobile", "r", "symbol", "text", "type" ] +}, { + "name" : "12mp", + "tags" : [ "12", "camera", "digits", "font", "image", "letters", "megapixel", "megapixels", "mp", "numbers", "pixel", "pixels", "quality", "resolution", "symbol", "text", "type" ] +}, { + "name" : "repartition", + "tags" : [ "arrow", "arrows", "data", "partition", "refresh", "renew", "repartition", "restore", "table" ] +}, { + "name" : "width_normal", + "tags" : [ ] +}, { + "name" : "h_plus_mobiledata", + "tags" : [ "+", "alphabet", "character", "data", "font", "h", "letter", "mobile", "network", "plus", "service", "symbol", "text", "type" ] +}, { + "name" : "hdr_enhanced_select", + "tags" : [ "add", "alphabet", "character", "dynamic", "enhance", "font", "hdr", "high", "letter", "plus", "range", "select", "symbol", "text", "type" ] +}, { + "name" : "mp", + "tags" : [ "alphabet", "character", "font", "image", "letter", "megapixel", "mp", "photo", "photography", "pixels", "quality", "resolution", "symbol", "text", "type" ] +}, { + "name" : "shape_line", + "tags" : [ "circle", "draw", "edit", "editing", "line", "shape", "square" ] +}, { + "name" : "9k_plus", + "tags" : [ "+", "9000", "9K", "alphabet", "character", "digit", "display", "font", "letter", "number", "pixel", "pixels", "plus", "resolution", "symbol", "text", "type", "video" ] +}, { + "name" : "5k", + "tags" : [ "5000", "5K", "alphabet", "character", "digit", "display", "font", "letter", "number", "pixel", "pixels", "resolution", "symbol", "text", "type", "video" ] +}, { + "name" : "hevc", + "tags" : [ "alphabet", "character", "coding", "efficiency", "font", "hevc", "high", "letter", "symbol", "text", "type", "video" ] +}, { + "name" : "currency_franc", + "tags" : [ "bill", "card", "cash", "coin", "commerce", "cost", "credit", "currency", "dollars", "finance", "franc", "money", "online", "pay", "payment", "price", "shopping", "symbol" ] +}, { + "name" : "8k_plus", + "tags" : [ "+", "7000", "8K", "alphabet", "character", "digit", "display", "font", "letter", "number", "pixel", "pixels", "plus", "resolution", "symbol", "text", "type", "video" ] +}, { + "name" : "hdr_on_select", + "tags" : [ "+", "alphabet", "camera", "character", "circle", "dynamic", "font", "hdr", "high", "letter", "on", "photo", "range", "select", "symbol", "text", "type" ] +}, { + "name" : "3k", + "tags" : [ "3000", "3K", "alphabet", "character", "digit", "display", "font", "letter", "number", "pixel", "pixels", "resolution", "symbol", "text", "type", "video" ] +}, { + "name" : "transcribe", + "tags" : [ ] +}, { + "name" : "width_wide", + "tags" : [ ] +}, { + "name" : "hdr_auto_select", + "tags" : [ "+", "A", "alphabet", "auto", "camera", "character", "circle", "dynamic", "font", "hdr", "high", "letter", "photo", "range", "select", "symbol", "text", "type" ] +}, { + "name" : "hls", + "tags" : [ "alphabet", "character", "develop", "developer", "engineer", "engineering", "font", "hls", "letter", "platform", "symbol", "text", "type" ] +}, { + "name" : "5k_plus", + "tags" : [ "+", "5000", "5K", "alphabet", "character", "digit", "display", "font", "letter", "number", "pixel", "pixels", "plus", "resolution", "symbol", "text", "type", "video" ] +}, { + "name" : "assist_walker", + "tags" : [ "accessibility", "accessible", "assist", "body", "disability", "handicap", "help", "human", "injured", "injury", "mobility", "person", "walk", "walker" ] +}, { + "name" : "hls_off", + "tags" : [ "alphabet", "character", "develop", "developer", "disabled", "enabled", "engineer", "engineering", "font", "hls", "letter", "off", "offline", "on", "platform", "slash", "symbol", "text", "type" ] +}, { + "name" : "18mp", + "tags" : [ "18", "camera", "digits", "font", "image", "letters", "megapixel", "megapixels", "mp", "numbers", "pixel", "pixels", "quality", "resolution", "symbol", "text", "type" ] +}, { + "name" : "format_overline", + "tags" : [ "alphabet", "character", "doc", "edit", "editing", "editor", "font", "format", "letter", "line", "overline", "sheet", "spreadsheet", "style", "symbol", "text", "type", "under", "writing" ] +}, { + "name" : "volcano", + "tags" : [ "crisis", "disaster", "eruption", "lava", "magma", "natural", "volcano" ] +}, { + "name" : "vaping_rooms", + "tags" : [ "allowed", "e-cigarette", "never", "no", "places", "prohibited", "smoke", "smoking", "tobacco", "vape", "vaping", "vapor", "warning", "zone" ] +}, { + "name" : "watch_off", + "tags" : [ "Android", "OS", "ar", "clock", "close", "gadget", "iOS", "off", "shut", "time", "vr", "watch", "wearables", "web", "wristwatch" ] +}, { + "name" : "9k", + "tags" : [ "9000", "9K", "alphabet", "character", "digit", "display", "font", "letter", "number", "pixel", "pixels", "resolution", "symbol", "text", "type", "video" ] +}, { + "name" : "23mp", + "tags" : [ "23", "camera", "digits", "font", "image", "letters", "megapixel", "megapixels", "mp", "numbers", "pixel", "pixels", "quality", "resolution", "symbol", "text", "type" ] +}, { + "name" : "propane", + "tags" : [ "gas", "nest", "propane" ] +}, { + "name" : "raw_off", + "tags" : [ "alphabet", "character", "disabled", "enabled", "font", "image", "letter", "off", "on", "original", "photo", "photography", "raw", "slash", "symbol", "text", "type" ] +}, { + "name" : "keyboard_option_key", + "tags" : [ "alt key", "key", "keyboard", "modifier key", "option" ] +}, { + "name" : "woman_2", + "tags" : [ "female", "gender", "girl", "lady", "social", "symbol", "woman", "women" ] +}, { + "name" : "2k_plus", + "tags" : [ "+", "2k", "alphabet", "character", "digit", "font", "letter", "number", "plus", "symbol", "text", "type" ] +}, { + "name" : "6k_plus", + "tags" : [ "+", "6000", "6K", "alphabet", "character", "digit", "display", "font", "letter", "number", "pixel", "pixels", "plus", "resolution", "symbol", "text", "type", "video" ] +}, { + "name" : "broadcast_on_personal", + "tags" : [ ] +}, { + "name" : "10mp", + "tags" : [ "10", "camera", "digits", "font", "image", "letters", "megapixel", "megapixels", "mp", "numbers", "pixel", "pixels", "quality", "resolution", "symbol", "text", "type" ] +}, { + "name" : "man_2", + "tags" : [ "boy", "gender", "male", "man", "social", "symbol" ] +}, { + "name" : "7k", + "tags" : [ "7000", "7K", "alphabet", "character", "digit", "display", "font", "letter", "number", "pixel", "pixels", "resolution", "symbol", "text", "type", "video" ] +}, { + "name" : "7k_plus", + "tags" : [ "+", "7000", "7K", "alphabet", "character", "digit", "display", "font", "letter", "number", "pixel", "pixels", "plus", "resolution", "symbol", "text", "type", "video" ] +}, { + "name" : "nearby_off", + "tags" : [ "disabled", "enabled", "nearby", "off", "on", "slash" ] +}, { + "name" : "3k_plus", + "tags" : [ "+", "3000", "3K", "alphabet", "character", "digit", "display", "font", "letter", "number", "pixel", "pixels", "plus", "resolution", "symbol", "text", "type", "video" ] +}, { + "name" : "6k", + "tags" : [ "6000", "6K", "alphabet", "character", "digit", "display", "font", "letter", "number", "pixel", "pixels", "resolution", "symbol", "text", "type", "video" ] +}, { + "name" : "hdr_off", + "tags" : [ "alphabet", "character", "disabled", "dynamic", "enabled", "enhance", "font", "hdr", "high", "letter", "off", "on", "range", "select", "slash", "symbol", "text", "type" ] +}, { + "name" : "roundabout_left", + "tags" : [ "arrow", "arrows", "direction", "directions", "left", "maps", "navigation", "path", "roundabout", "route", "sign", "traffic" ] +}, { + "name" : "hdr_off_select", + "tags" : [ "alphabet", "camera", "character", "circle", "disabled", "dynamic", "enabled", "font", "hdr", "high", "letter", "off", "on", "photo", "range", "select", "slash", "symbol", "text", "type" ] +}, { + "name" : "bedtime_off", + "tags" : [ "bedtime", "disabled", "lunar", "moon", "night", "nightime", "off", "offline", "slash", "sleep" ] +}, { + "name" : "18_up_rating", + "tags" : [ ] +}, { + "name" : "turn_sharp_left", + "tags" : [ "arrow", "arrows", "direction", "directions", "left", "maps", "navigation", "path", "route", "sharp", "sign", "traffic", "turn" ] +}, { + "name" : "11mp", + "tags" : [ "11", "camera", "digits", "font", "image", "letters", "megapixel", "megapixels", "mp", "numbers", "pixel", "pixels", "quality", "resolution", "symbol", "text", "type" ] +}, { + "name" : "roller_shades_closed", + "tags" : [ "blinds", "closed", "cover", "curtains", "nest", "roller", "shade", "shutter", "sunshade" ] +}, { + "name" : "20mp", + "tags" : [ "20", "camera", "digits", "font", "image", "letters", "megapixel", "megapixels", "mp", "numbers", "pixel", "pixels", "quality", "resolution", "symbol", "text", "type" ] +}, { + "name" : "blinds", + "tags" : [ "blinds", "cover", "curtains", "nest", "open", "shade", "shutter", "sunshade" ] +}, { + "name" : "3mp", + "tags" : [ "3", "camera", "digit", "font", "image", "letters", "megapixel", "megapixels", "mp", "number", "pixel", "pixels", "quality", "resolution", "symbol", "text", "type" ] +}, { + "name" : "blind", + "tags" : [ "accessibility", "accessible", "assist", "blind", "body", "cane", "disability", "handicap", "help", "human", "mobility", "person", "walk", "walker" ] +}, { + "name" : "emergency_recording", + "tags" : [ "alert", "attention", "camera", "caution", "danger", "emergency", "film", "filming", "hardware", "image", "important", "motion", "notification", "picture", "record", "video", "videography", "warning" ] +}, { + "name" : "curtains", + "tags" : [ "blinds", "cover", "curtains", "nest", "open", "shade", "shutter", "sunshade" ] +}, { + "name" : "13mp", + "tags" : [ "13", "camera", "digits", "font", "image", "letters", "megapixel", "megapixels", "mp", "numbers", "pixel", "pixels", "quality", "resolution", "symbol", "text", "type" ] +}, { + "name" : "5mp", + "tags" : [ "5", "camera", "digit", "font", "image", "letters", "megapixel", "megapixels", "mp", "number", "pixel", "pixels", "quality", "resolution", "symbol", "text", "type" ] +}, { + "name" : "21mp", + "tags" : [ "21", "camera", "digits", "font", "image", "letters", "megapixel", "megapixels", "mp", "numbers", "pixel", "pixels", "quality", "resolution", "symbol", "text", "type" ] +}, { + "name" : "blinds_closed", + "tags" : [ "blinds", "closed", "cover", "curtains", "nest", "shade", "shutter", "sunshade" ] +}, { + "name" : "16mp", + "tags" : [ "16", "camera", "digits", "font", "image", "letters", "megapixel", "megapixels", "mp", "numbers", "pixel", "pixels", "quality", "resolution", "symbol", "text", "type" ] +}, { + "name" : "17mp", + "tags" : [ "17", "camera", "digits", "font", "image", "letters", "megapixel", "megapixels", "mp", "numbers", "pixel", "pixels", "quality", "resolution", "symbol", "text", "type" ] +}, { + "name" : "2mp", + "tags" : [ "2", "camera", "digit", "font", "image", "letters", "megapixel", "megapixels", "mp", "number", "pixel", "pixels", "quality", "resolution", "symbol", "text", "type" ] +}, { + "name" : "15mp", + "tags" : [ "15", "camera", "digits", "font", "image", "letters", "megapixel", "megapixels", "mp", "numbers", "pixel", "pixels", "quality", "resolution", "symbol", "text", "type" ] +}, { + "name" : "desk", + "tags" : [ ] +}, { + "name" : "no_adult_content", + "tags" : [ ] +}, { + "name" : "14mp", + "tags" : [ "14", "camera", "digits", "font", "image", "letters", "megapixel", "megapixels", "mp", "numbers", "pixel", "pixels", "quality", "resolution", "symbol", "text", "type" ] +}, { + "name" : "22mp", + "tags" : [ "22", "camera", "digits", "font", "image", "letters", "megapixel", "megapixels", "mp", "numbers", "pixel", "pixels", "quality", "resolution", "symbol", "text", "type" ] +}, { + "name" : "vertical_shades", + "tags" : [ "blinds", "cover", "curtains", "nest", "open", "shade", "shutter", "sunshade", "vertical" ] +}, { + "name" : "vertical_shades_closed", + "tags" : [ "blinds", "closed", "cover", "curtains", "nest", "roller", "shade", "shutter", "sunshade" ] +}, { + "name" : "curtains_closed", + "tags" : [ "blinds", "closed", "cover", "curtains", "nest", "shade", "shutter", "sunshade" ] +}, { + "name" : "broadcast_on_home", + "tags" : [ ] +}, { + "name" : "4mp", + "tags" : [ "4", "camera", "digit", "font", "image", "letters", "megapixel", "megapixels", "mp", "number", "pixel", "pixels", "quality", "resolution", "symbol", "text", "type" ] +}, { + "name" : "19mp", + "tags" : [ "19", "camera", "digits", "font", "image", "letters", "megapixel", "megapixels", "mp", "numbers", "pixel", "pixels", "quality", "resolution", "symbol", "text", "type" ] +}, { + "name" : "nest_cam_wired_stand", + "tags" : [ "camera", "film", "filming", "hardware", "image", "motion", "nest", "picture", "stand", "video", "videography", "wired" ] +}, { + "name" : "9mp", + "tags" : [ "9", "camera", "digit", "font", "image", "letters", "megapixel", "megapixels", "mp", "number", "pixel", "pixels", "quality", "resolution", "symbol", "text", "type" ] +}, { + "name" : "7mp", + "tags" : [ "7", "camera", "digit", "font", "image", "letters", "megapixel", "megapixels", "mp", "number", "pixel", "pixels", "quality", "resolution", "symbol", "text", "type" ] +}, { + "name" : "8mp", + "tags" : [ "8", "camera", "digit", "font", "image", "letters", "megapixel", "megapixels", "mp", "number", "pixel", "pixels", "quality", "resolution", "symbol", "text", "type" ] +}, { + "name" : "6mp", + "tags" : [ "6", "camera", "digit", "font", "image", "letters", "megapixel", "megapixels", "mp", "number", "pixel", "pixels", "quality", "resolution", "symbol", "text", "type" ] +}, { + "name" : "devices_fold", + "tags" : [ "Android", "OS", "cell", "device", "fold", "foldable", "hardware", "iOS", "mobile", "phone", "tablet" ] +}, { + "name" : "vape_free", + "tags" : [ "disabled", "e-cigarette", "enabled", "free", "never", "no", "off", "on", "places", "prohibited", "slash", "smoke", "smoking", "tobacco", "vape", "vaping", "vapor", "warning", "zone" ] +}, { + "name" : "ramp_left", + "tags" : [ "arrow", "arrows", "direction", "directions", "left", "maps", "navigation", "path", "ramp", "route", "sign", "traffic" ] +}, { + "name" : "ramp_right", + "tags" : [ "arrow", "arrows", "direction", "directions", "maps", "navigation", "path", "ramp", "right", "route", "sign", "traffic" ] +}, { + "name" : "video_chat", + "tags" : [ "bubble", "cam", "camera", "chat", "comment", "communicate", "facetime", "feedback", "message", "speech", "video", "voice" ] +}, { + "name" : "type_specimen", + "tags" : [ ] +}, { + "name" : "man_4", + "tags" : [ "abstract", "boy", "gender", "male", "man", "social", "symbol" ] +}, { + "name" : "fluorescent", + "tags" : [ "bright", "fluorescent", "lamp", "light", "lightbulb" ] +}, { + "name" : "man_3", + "tags" : [ "abstract", "boy", "gender", "male", "man", "social", "symbol" ] +}, { + "name" : "fire_hydrant_alt", + "tags" : [ ] +}, { + "name" : "macro_off", + "tags" : [ "camera", "disabled", "enabled", "flower", "garden", "image", "macro", "off", "offline", "on", "slash" ] +} ] \ No newline at end of file From ac31c06f1ebe46129f83abb3549349c6e6f5269b Mon Sep 17 00:00:00 2001 From: rusikv Date: Tue, 11 Jul 2023 15:36:07 +0300 Subject: [PATCH 13/22] Removed unused service, generic event type used --- .../modules/home/components/event/event-table-config.ts | 6 ++---- .../home/components/event/event-table.component.ts | 9 +++------ 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/event/event-table-config.ts b/ui-ngx/src/app/modules/home/components/event/event-table-config.ts index 7382633e33..565dbf14bf 100644 --- a/ui-ngx/src/app/modules/home/components/event/event-table-config.ts +++ b/ui-ngx/src/app/modules/home/components/event/event-table-config.ts @@ -21,7 +21,7 @@ import { EntityTableColumn, EntityTableConfig } from '@home/models/entity/entities-table-config.models'; -import { DebugEventType, DebugRuleNodeEventBody, Event, EventType, FilterEventBody } from '@shared/models/event.models'; +import { DebugEventType, Event, EventBody, EventType, FilterEventBody } from '@shared/models/event.models'; import { TimePageLink } from '@shared/models/page/page-link'; import { TranslateService } from '@ngx-translate/core'; import { DatePipe } from '@angular/common'; @@ -49,7 +49,6 @@ import { EventFilterPanelData, FilterEntityColumn } from '@home/components/event/event-filter-panel.component'; -import { NodeScriptTestService } from '@core/services/script/node-script-test.service'; export class EventTableConfig extends EntityTableConfig { @@ -87,9 +86,8 @@ export class EventTableConfig extends EntityTableConfig { private overlay: Overlay, private viewContainerRef: ViewContainerRef, private cd: ChangeDetectorRef, - private nodeScriptTestService: NodeScriptTestService, public testButtonLabel?: string, - private debugEventSelected?: EventEmitter) { + private debugEventSelected?: EventEmitter) { super(); this.loadDataOnInit = false; this.tableTitle = ''; diff --git a/ui-ngx/src/app/modules/home/components/event/event-table.component.ts b/ui-ngx/src/app/modules/home/components/event/event-table.component.ts index 80394de979..8a1d71eaf4 100644 --- a/ui-ngx/src/app/modules/home/components/event/event-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/event/event-table.component.ts @@ -32,10 +32,9 @@ import { EntitiesTableComponent } from '@home/components/entity/entities-table.c import { EventTableConfig } from './event-table-config'; import { EventService } from '@core/http/event.service'; import { DialogService } from '@core/services/dialog.service'; -import { DebugEventType, DebugRuleNodeEventBody, EventType } from '@shared/models/event.models'; +import { DebugEventType, EventBody, EventType } from '@shared/models/event.models'; import { Overlay } from '@angular/cdk/overlay'; import { Subscription } from 'rxjs'; -import { NodeScriptTestService } from '@core/services/script/node-script-test.service'; import { isNotEmptyStr } from '@core/utils'; @Component({ @@ -109,7 +108,7 @@ export class EventTableComponent implements OnInit, AfterViewInit, OnDestroy { } @Output() - debugEventSelected = new EventEmitter(null); + debugEventSelected = new EventEmitter(); @ViewChild(EntitiesTableComponent, {static: true}) entitiesTable: EntitiesTableComponent; @@ -124,8 +123,7 @@ export class EventTableComponent implements OnInit, AfterViewInit, OnDestroy { private dialog: MatDialog, private overlay: Overlay, private viewContainerRef: ViewContainerRef, - private cd: ChangeDetectorRef, - private nodeScriptTestService: NodeScriptTestService) { + private cd: ChangeDetectorRef) { } ngOnInit() { @@ -144,7 +142,6 @@ export class EventTableComponent implements OnInit, AfterViewInit, OnDestroy { this.overlay, this.viewContainerRef, this.cd, - this.nodeScriptTestService, this.ruleNodeTestButtonLabel, this.debugEventSelected ); From 1e7b205cc90fc54c6533360a87524873ab43edc9 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Wed, 12 Jul 2023 15:14:42 +0300 Subject: [PATCH 14/22] UI: Fixed style in clear button for unit input --- .../shared/components/unit-input.component.html | 1 + ui-ngx/src/form.scss | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/ui-ngx/src/app/shared/components/unit-input.component.html b/ui-ngx/src/app/shared/components/unit-input.component.html index 141ab322d4..3686796dbf 100644 --- a/ui-ngx/src/app/shared/components/unit-input.component.html +++ b/ui-ngx/src/app/shared/components/unit-input.component.html @@ -22,6 +22,7 @@ [matAutocomplete]="unitsAutocomplete"> - - - -
-
- -
-
-
-
- - - - - - -
-
-
-
- - -
- +
+ + + +
diff --git a/ui-ngx/src/app/shared/components/dialog/material-icons-dialog.component.scss b/ui-ngx/src/app/shared/components/dialog/material-icons-dialog.component.scss index 849b646234..afd8d1cfcb 100644 --- a/ui-ngx/src/app/shared/components/dialog/material-icons-dialog.component.scss +++ b/ui-ngx/src/app/shared/components/dialog/material-icons-dialog.component.scss @@ -14,36 +14,9 @@ * limitations under the License. */ :host { - .tb-material-icons-dialog { - position: relative; - } - .tb-icons-load { - top: 64px; - z-index: 3; - background: rgba(255, 255, 255, .75); - } -} - -:host ::ng-deep { - .tb-material-icons-dialog { - button.mat-mdc-button-base.tb-select-icon-button { - width: 56px; - min-width: 56px; - height: 56px; - padding: 16px; - margin: 10px; - border: solid 1px #ffa500; - border-radius: 0; - line-height: 0; - display: inline-block; - vertical-align: baseline; - .mat-icon { - width: 24px; - margin: 0; - height: 24px; - vertical-align: initial; - font-size: 24px; - } - } + .tb-close-button { + position: absolute; + top: 6px; + right: 6px; } } diff --git a/ui-ngx/src/app/shared/components/dialog/material-icons-dialog.component.ts b/ui-ngx/src/app/shared/components/dialog/material-icons-dialog.component.ts index e63b6a0c9c..b6321c966d 100644 --- a/ui-ngx/src/app/shared/components/dialog/material-icons-dialog.component.ts +++ b/ui-ngx/src/app/shared/components/dialog/material-icons-dialog.component.ts @@ -14,18 +14,12 @@ /// limitations under the License. /// -import { AfterViewInit, Component, Inject, OnInit, QueryList, ViewChildren } from '@angular/core'; +import { Component, Inject } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { Router } from '@angular/router'; import { DialogComponent } from '@shared/components/dialog.component'; -import { UtilsService } from '@core/services/utils.service'; -import { UntypedFormControl } from '@angular/forms'; -import { merge, Observable } from 'rxjs'; -import { delay, map, mapTo, mergeMap, share, startWith, tap } from 'rxjs/operators'; -import { ResourcesService } from '@core/services/resources.service'; -import { getMaterialIcons } from '@shared/models/icon.models'; export interface MaterialIconsDialogData { icon: string; @@ -37,63 +31,16 @@ export interface MaterialIconsDialogData { providers: [], styleUrls: ['./material-icons-dialog.component.scss'] }) -export class MaterialIconsDialogComponent extends DialogComponent - implements OnInit, AfterViewInit { - - @ViewChildren('iconButtons') iconButtons: QueryList; +export class MaterialIconsDialogComponent extends DialogComponent { selectedIcon: string; - icons$: Observable>; - loadingIcons$: Observable; - - showAllControl: UntypedFormControl; constructor(protected store: Store, protected router: Router, @Inject(MAT_DIALOG_DATA) public data: MaterialIconsDialogData, - private utils: UtilsService, - private resourcesService: ResourcesService, public dialogRef: MatDialogRef) { super(store, router, dialogRef); this.selectedIcon = data.icon; - this.showAllControl = new UntypedFormControl(false); - } - - ngOnInit(): void { - this.icons$ = this.showAllControl.valueChanges.pipe( - map((showAll) => ({firstTime: false, showAll})), - startWith<{firstTime: boolean; showAll: boolean}>({firstTime: true, showAll: false}), - mergeMap((data) => { - const res = getMaterialIcons(this.resourcesService, data.showAll, ''); - if (data.showAll) { - return res.pipe(delay(100)); - } else { - return data.firstTime ? res : res.pipe(delay(50)); - } - }), - share() - ); - } - - ngAfterViewInit(): void { - this.loadingIcons$ = merge( - this.showAllControl.valueChanges.pipe( - mapTo(true), - ), - this.iconButtons.changes.pipe( - delay(100), - mapTo( false), - ) - ).pipe( - tap((loadingIcons) => { - if (loadingIcons) { - this.showAllControl.disable({emitEvent: false}); - } else { - this.showAllControl.enable({emitEvent: false}); - } - }), - share() - ); } selectIcon(icon: string) { diff --git a/ui-ngx/src/app/shared/components/material-icon-select.component.html b/ui-ngx/src/app/shared/components/material-icon-select.component.html index 5cf7cb6de7..8bae8c3435 100644 --- a/ui-ngx/src/app/shared/components/material-icon-select.component.html +++ b/ui-ngx/src/app/shared/components/material-icon-select.component.html @@ -29,7 +29,13 @@
- {{materialIconFormGroup.get('icon').value}} + diff --git a/ui-ngx/src/app/shared/components/material-icon-select.component.scss b/ui-ngx/src/app/shared/components/material-icon-select.component.scss index 6bfd308ae5..b008fc6838 100644 --- a/ui-ngx/src/app/shared/components/material-icon-select.component.scss +++ b/ui-ngx/src/app/shared/components/material-icon-select.component.scss @@ -22,20 +22,23 @@ border: solid 1px rgba(0, 0, 0, .27); box-sizing: initial; } - &.icon-box { - border: 1px solid rgba(0, 0, 0, 0.12); - border-radius: 4px; - cursor: pointer; - box-sizing: border-box; - padding: 8px; - height: 40px; - width: 40px; - font-size: 22px; - vertical-align: middle; - &.disabled { - cursor: initial; - color: rgba(0, 0, 0, 0.38); - } + } +} + +:host ::ng-deep { + button.mat-mdc-button-base.icon-box { + width: 40px; + min-width: 40px; + height: 40px; + padding: 7px; + &:not(:disabled) { + color: rgba(0, 0, 0, 0.87); + } + > .mat-icon { + width: 24px; + height: 24px; + font-size: 24px; + margin: 0; } } } diff --git a/ui-ngx/src/app/shared/components/material-icon-select.component.ts b/ui-ngx/src/app/shared/components/material-icon-select.component.ts index b8bb7ed25b..740bb4545a 100644 --- a/ui-ngx/src/app/shared/components/material-icon-select.component.ts +++ b/ui-ngx/src/app/shared/components/material-icon-select.component.ts @@ -14,15 +14,18 @@ /// limitations under the License. /// -import { ChangeDetectorRef, Component, forwardRef, Input, OnInit } from '@angular/core'; +import { ChangeDetectorRef, Component, forwardRef, Input, OnInit, Renderer2, ViewContainerRef } from '@angular/core'; import { PageComponent } from '@shared/components/page.component'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; -import { ControlValueAccessor, UntypedFormBuilder, UntypedFormGroup, NG_VALUE_ACCESSOR } from '@angular/forms'; +import { ControlValueAccessor, NG_VALUE_ACCESSOR, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { DialogService } from '@core/services/dialog.service'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { TranslateService } from '@ngx-translate/core'; import { coerceBoolean } from '@shared/decorators/coercion'; +import { TbPopoverService } from '@shared/components/popover.service'; +import { MaterialIconsComponent } from '@shared/components/material-icons.component'; +import { MatButton } from '@angular/material/button'; @Component({ selector: 'tb-material-icon-select', @@ -81,6 +84,9 @@ export class MaterialIconSelectComponent extends PageComponent implements OnInit constructor(protected store: Store, private dialogs: DialogService, private translate: TranslateService, + private popoverService: TbPopoverService, + private renderer: Renderer2, + private viewContainerRef: ViewContainerRef, private fb: UntypedFormBuilder, private cd: ChangeDetectorRef) { super(store); @@ -142,6 +148,32 @@ export class MaterialIconSelectComponent extends PageComponent implements OnInit } } + openIconPopup($event: Event, matButton: MatButton) { + if ($event) { + $event.stopPropagation(); + } + const trigger = matButton._elementRef.nativeElement; + if (this.popoverService.hasPopover(trigger)) { + this.popoverService.hidePopover(trigger); + } else { + const materialIconsPopover = this.popoverService.displayPopover(trigger, this.renderer, + this.viewContainerRef, MaterialIconsComponent, 'left', true, null, + { + selectedIcon: this.materialIconFormGroup.get('icon').value + }, + {}, + {}, {}, true); + materialIconsPopover.tbComponentRef.instance.popover = materialIconsPopover; + materialIconsPopover.tbComponentRef.instance.iconSelected.subscribe((icon) => { + materialIconsPopover.hide(); + this.materialIconFormGroup.patchValue( + {icon}, {emitEvent: true} + ); + this.cd.markForCheck(); + }); + } + } + clear() { this.materialIconFormGroup.get('icon').patchValue(null, {emitEvent: true}); this.cd.markForCheck(); diff --git a/ui-ngx/src/app/shared/components/material-icons.component.html b/ui-ngx/src/app/shared/components/material-icons.component.html new file mode 100644 index 0000000000..39404a9998 --- /dev/null +++ b/ui-ngx/src/app/shared/components/material-icons.component.html @@ -0,0 +1,65 @@ + +
+
icon.icons
+ + search + + + + +
+ + + + +
+
+ + +
+
+
{{ 'icon.no-icons-found' | translate:{iconSearch: searchIconControl.value} }}
+
+
+
diff --git a/ui-ngx/src/app/shared/components/material-icons.component.scss b/ui-ngx/src/app/shared/components/material-icons.component.scss new file mode 100644 index 0000000000..23b959d118 --- /dev/null +++ b/ui-ngx/src/app/shared/components/material-icons.component.scss @@ -0,0 +1,61 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +.tb-material-icons-panel { + width: 100%; + display: flex; + flex-direction: column; + gap: 16px; + align-items: center; + .tb-material-icons-title { + font-size: 16px; + font-weight: 500; + line-height: 24px; + letter-spacing: 0.25px; + color: rgba(0, 0, 0, 0.87); + } + .tb-material-icons-title, .tb-material-icons-search, .tb-material-icons-show-more { + width: 100%; + } + .tb-material-icons-viewport { + min-height: 144px; + } + .tb-material-icons-row { + display: flex; + flex-direction: row; + gap: 12px; + } + .tb-material-icons-row + .tb-material-icons-row { + margin-top: 12px; + } + .tb-no-data-available { + min-height: 144px; + } + button.mat-mdc-button-base.tb-select-icon-button { + width: 36px; + min-width: 36px; + height: 36px; + padding: 6px; + &:not(.mat-primary) { + color: rgba(0, 0, 0, 0.54); + } + > .mat-icon { + width: 24px; + height: 24px; + font-size: 24px; + margin: 0; + } + } +} diff --git a/ui-ngx/src/app/shared/components/material-icons.component.ts b/ui-ngx/src/app/shared/components/material-icons.component.ts index 5588540018..9347243af2 100644 --- a/ui-ngx/src/app/shared/components/material-icons.component.ts +++ b/ui-ngx/src/app/shared/components/material-icons.component.ts @@ -1,24 +1,135 @@ +/// +/// Copyright © 2016-2023 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + import { PageComponent } from '@shared/components/page.component'; -import { OnInit } from '@angular/core'; +import { + ChangeDetectorRef, + Component, + EventEmitter, + Input, + OnInit, + Output, + ViewChild, + ViewEncapsulation +} from '@angular/core'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { UntypedFormControl } from '@angular/forms'; -import { BehaviorSubject, Observable, ReplaySubject } from 'rxjs'; +import { BehaviorSubject, combineLatest, debounce, Observable, of, timer } from 'rxjs'; +import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling'; +import { getMaterialIcons, MaterialIcon } from '@shared/models/icon.models'; +import { distinctUntilChanged, map, mergeMap, share, startWith, tap } from 'rxjs/operators'; +import { ResourcesService } from '@core/services/resources.service'; +import { TbPopoverComponent } from '@shared/components/popover.component'; +import { BreakpointObserver } from '@angular/cdk/layout'; +import { MediaBreakpoints } from '@shared/models/constants'; +@Component({ + selector: 'tb-material-icons', + templateUrl: './material-icons.component.html', + providers: [], + styleUrls: ['./material-icons.component.scss'], + encapsulation: ViewEncapsulation.None +}) export class MaterialIconsComponent extends PageComponent implements OnInit { - searchIconsControl: UntypedFormControl; + @ViewChild('iconsPanel') + iconsPanel: CdkVirtualScrollViewport; + + @Input() + selectedIcon: string; + + @Input() + popover: TbPopoverComponent; + + @Output() + iconSelected = new EventEmitter(); + + iconRows$: Observable; showAllSubject = new BehaviorSubject(false); + searchIconControl: UntypedFormControl; + + iconsRowHeight = 48; + + iconsPanelHeight: string; + iconsPanelWidth: string; - icons$: Observable>; + notFound = false; - constructor(protected store: Store) { + constructor(protected store: Store, + private resourcesService: ResourcesService, + private breakpointObserver: BreakpointObserver, + private cd: ChangeDetectorRef) { super(store); - this.searchIconsControl = new UntypedFormControl(''); + this.searchIconControl = new UntypedFormControl(''); } ngOnInit(): void { + const iconsRowSize = this.breakpointObserver.isMatched(MediaBreakpoints['lt-md']) ? 8 : 11; + this.calculatePanelSize(iconsRowSize); + const iconsRowSizeObservable = this.breakpointObserver + .observe(MediaBreakpoints['lt-md']).pipe( + map((state) => state.matches ? 8 : 11), + startWith(iconsRowSize), + ); + this.iconRows$ = combineLatest({showAll: this.showAllSubject.asObservable(), + rowSize: iconsRowSizeObservable, + searchText: this.searchIconControl.valueChanges.pipe( + startWith(''), + debounce((searchText) => searchText ? timer(150) : of({})), + )}).pipe( + map((data) => { + if (data.searchText && !data.showAll) { + data.showAll = true; + this.showAllSubject.next(true); + } + return data; + }), + distinctUntilChanged((p, c) => c.showAll === p.showAll && c.searchText === p.searchText && c.rowSize === p.rowSize), + mergeMap((data) => getMaterialIcons(this.resourcesService, data.rowSize, data.showAll, data.searchText).pipe( + map(iconRows => ({iconRows, iconsRowSize: data.rowSize})) + )), + tap((data) => { + this.notFound = !data.iconRows.length; + this.calculatePanelSize(data.iconsRowSize, data.iconRows.length); + this.cd.markForCheck(); + setTimeout(() => { + this.checkSize(); + }, 0); + }), + map((data) => data.iconRows), + share() + ); + } + + clearSearch() { + this.searchIconControl.patchValue('', {emitEvent: true}); + } + selectIcon(icon: MaterialIcon) { + this.iconSelected.emit(icon.name); } + private calculatePanelSize(iconsRowSize: number, iconRows = 4) { + this.iconsPanelHeight = Math.min(iconRows * this.iconsRowHeight, 10 * this.iconsRowHeight) + 'px'; + this.iconsPanelWidth = (iconsRowSize * 36 + (iconsRowSize - 1) * 12 + 6) + 'px'; + } + + private checkSize() { + this.iconsPanel?.checkViewportSize(); + this.popover?.updatePosition(); + } } diff --git a/ui-ngx/src/app/shared/components/popover.component.ts b/ui-ngx/src/app/shared/components/popover.component.ts index d6d092d03c..91f5a2e902 100644 --- a/ui-ngx/src/app/shared/components/popover.component.ts +++ b/ui-ngx/src/app/shared/components/popover.component.ts @@ -63,8 +63,10 @@ import { coerceBoolean } from '@shared/decorators/coercion'; export type TbPopoverTrigger = 'click' | 'focus' | 'hover' | null; @Directive({ + // eslint-disable-next-line @angular-eslint/directive-selector selector: '[tb-popover]', exportAs: 'tbPopover', + // eslint-disable-next-line @angular-eslint/no-host-metadata-property host: { '[class.tb-popover-open]': 'visible' } @@ -265,12 +267,20 @@ export class TbPopoverDirective implements OnChanges, OnDestroy, AfterViewInit { } else if (delay > 0) { this.delayTimer = setTimeout(() => { this.delayTimer = undefined; - isEnter ? this.show() : this.hide(); + if (isEnter) { + this.show(); + } else { + this.hide(); + } }, delay * 1000); } else { // `isOrigin` is used due to the tooltip will not hide immediately // (may caused by the fade-out animation). - isEnter && isOrigin ? this.show() : this.hide(); + if (isEnter && isOrigin) { + this.show(); + } else { + this.hide(); + } } } @@ -345,15 +355,15 @@ export class TbPopoverDirective implements OnChanges, OnDestroy, AfterViewInit { ` }) -export class TbPopoverComponent implements OnDestroy, OnInit { +export class TbPopoverComponent implements OnDestroy, OnInit { @ViewChild('overlay', { static: false }) overlay!: CdkConnectedOverlay; @ViewChild('popoverRoot', { static: false }) popoverRoot!: ElementRef; @ViewChild('popover', { static: false }) popover!: ElementRef; tbContent: string | TemplateRef | null = null; - tbComponentFactory: ComponentFactory | null = null; - tbComponentRef: ComponentRef | null = null; + tbComponentFactory: ComponentFactory | null = null; + tbComponentRef: ComponentRef | null = null; tbComponentContext: any; tbComponentInjector: Injector | null = null; tbComponentStyle: { [klass: string]: any } = {}; diff --git a/ui-ngx/src/app/shared/components/popover.service.ts b/ui-ngx/src/app/shared/components/popover.service.ts index f547200316..1bef922ec1 100644 --- a/ui-ngx/src/app/shared/components/popover.service.ts +++ b/ui-ngx/src/app/shared/components/popover.service.ts @@ -65,7 +65,7 @@ export class TbPopoverService { displayPopover(trigger: Element, renderer: Renderer2, hostView: ViewContainerRef, componentType: Type, preferredPlacement: PopoverPlacement = 'top', hideOnClickOutside = true, injector?: Injector, context?: any, overlayStyle: any = {}, popoverStyle: any = {}, style?: any, - showCloseButton = true): TbPopoverComponent { + showCloseButton = true): TbPopoverComponent { const componentRef = this.createPopoverRef(hostView); return this.displayPopoverWithComponentRef(componentRef, trigger, renderer, componentType, preferredPlacement, hideOnClickOutside, injector, context, overlayStyle, popoverStyle, style, showCloseButton); @@ -74,7 +74,7 @@ export class TbPopoverService { displayPopoverWithComponentRef(componentRef: ComponentRef, trigger: Element, renderer: Renderer2, componentType: Type, preferredPlacement: PopoverPlacement = 'top', hideOnClickOutside = true, injector?: Injector, context?: any, overlayStyle: any = {}, - popoverStyle: any = {}, style?: any, showCloseButton = true): TbPopoverComponent { + popoverStyle: any = {}, style?: any, showCloseButton = true): TbPopoverComponent { const component = componentRef.instance; this.popoverWithTriggers.push({ trigger, diff --git a/ui-ngx/src/app/shared/components/public-api.ts b/ui-ngx/src/app/shared/components/public-api.ts index 3ed56d0256..04508266e9 100644 --- a/ui-ngx/src/app/shared/components/public-api.ts +++ b/ui-ngx/src/app/shared/components/public-api.ts @@ -26,3 +26,4 @@ export * from './resource/resource-autocomplete.component'; export * from './toggle-header.component'; export * from './toggle-select.component'; export * from './unit-input.component'; +export * from './material-icons.component'; diff --git a/ui-ngx/src/app/shared/models/icon.models.ts b/ui-ngx/src/app/shared/models/icon.models.ts index c774b65ae5..48b643d235 100644 --- a/ui-ngx/src/app/shared/models/icon.models.ts +++ b/ui-ngx/src/app/shared/models/icon.models.ts @@ -1,11 +1,27 @@ -import { Unit, units } from '@shared/models/unit.models'; +/// +/// Copyright © 2016-2023 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + import { ResourcesService } from '@core/services/resources.service'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; -import { isEmptyStr, isNotEmptyStr } from '@core/utils'; +import { isNotEmptyStr } from '@core/utils'; export interface MaterialIcon { name: string; + displayName?: string; tags: string[]; } @@ -16,21 +32,41 @@ const searchIconTags = (icon: MaterialIcon, searchText: string): boolean => const searchIcons = (_icons: Array, searchText: string): Array => _icons.filter( i => i.name.toUpperCase().includes(searchText.toUpperCase()) || + i.displayName.toUpperCase().includes(searchText.toUpperCase()) || searchIconTags(i, searchText) ); -const getCommonMaterialIcons = (icons: Array): Array => icons.slice(0, 44); +const getCommonMaterialIcons = (icons: Array, chunkSize: number): Array => icons.slice(0, chunkSize * 4); -export const getMaterialIcons = (resourcesService: ResourcesService, all = false, searchText: string): Observable => - resourcesService.loadJsonResource>('/assets/metadata/material-icons.json').pipe( +export const getMaterialIcons = (resourcesService: ResourcesService, chunkSize = 11, + all = false, searchText: string): Observable => + resourcesService.loadJsonResource>('/assets/metadata/material-icons.json', + (icons) => { + for (const icon of icons) { + const words = icon.name.replace(/_/g, ' ').split(' '); + for (let i = 0; i < words.length; i++) { + words[i] = words[i].charAt(0).toUpperCase() + words[i].slice(1); + } + icon.displayName = words.join(' '); + } + return icons; + } + ).pipe( map((icons) => { if (isNotEmptyStr(searchText)) { return searchIcons(icons, searchText); } else if (!all) { - return getCommonMaterialIcons(icons); + return getCommonMaterialIcons(icons, chunkSize); } else { return icons; } }), - map((icons) => icons.map(icon => icon.name)) + map((icons) => { + const iconChunks: MaterialIcon[][] = []; + for (let i = 0; i < icons.length; i += chunkSize) { + const chunk = icons.slice(i, i + chunkSize); + iconChunks.push(chunk); + } + return iconChunks; + }) ); diff --git a/ui-ngx/src/app/shared/shared.module.ts b/ui-ngx/src/app/shared/shared.module.ts index f7c37e4761..25eee9ca08 100644 --- a/ui-ngx/src/app/shared/shared.module.ts +++ b/ui-ngx/src/app/shared/shared.module.ts @@ -195,6 +195,7 @@ import { ToggleHeaderComponent, ToggleOption } from '@shared/components/toggle-h import { RuleChainSelectComponent } from '@shared/components/rule-chain/rule-chain-select.component'; import { ToggleSelectComponent } from '@shared/components/toggle-select.component'; import { UnitInputComponent } from '@shared/components/unit-input.component'; +import { MaterialIconsComponent } from '@shared/components/material-icons.component'; export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService) { return markedOptionsService; @@ -369,6 +370,7 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService) ToggleOption, ToggleSelectComponent, UnitInputComponent, + MaterialIconsComponent, RuleChainSelectComponent ], imports: [ @@ -600,6 +602,7 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService) ToggleOption, ToggleSelectComponent, UnitInputComponent, + MaterialIconsComponent, RuleChainSelectComponent ] }) diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 82f10b7f4c..bc3351aa83 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -68,7 +68,8 @@ "less": "Less", "skip": "Skip", "send": "Send", - "reset": "Reset" + "reset": "Reset", + "show-more": "Show more" }, "aggregation": { "aggregation": "Aggregation", @@ -5501,9 +5502,12 @@ }, "icon": { "icon": "Icon", + "icons": "Icons", "select-icon": "Select icon", "material-icons": "Material icons", - "show-all": "Show all icons" + "show-all": "Show all icons", + "search-icon": "Search icon", + "no-icons-found": "No icons found for '{{iconSearch}}'" }, "phone-input": { "phone-input-label": "Phone number", diff --git a/ui-ngx/src/form.scss b/ui-ngx/src/form.scss index 1f27e59279..8197e32f6c 100644 --- a/ui-ngx/src/form.scss +++ b/ui-ngx/src/form.scss @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +@import './scss/constants'; + .tb-default, .tb-dark { .tb-form-panel { box-shadow: 0 0 10px 6px rgba(11, 17, 51, 0.04); @@ -177,6 +180,13 @@ opacity: 0; } } + &:not(.mat-mdc-form-field-has-icon-prefix) { + .mat-mdc-text-field-wrapper { + &.mdc-text-field--outlined, &:not(.mdc-text-field--outlined) { + padding-left: 12px; + } + } + } &:not(.mat-mdc-form-field-has-icon-suffix) { .mat-mdc-text-field-wrapper { &.mdc-text-field--outlined, &:not(.mdc-text-field--outlined) { @@ -186,7 +196,6 @@ } .mat-mdc-text-field-wrapper { &.mdc-text-field--outlined, &:not(.mdc-text-field--outlined) { - padding-left: 12px; &:not(.mdc-text-field--focused):not(.mdc-text-field--disabled):not(:hover) { .mdc-notched-outline__leading, .mdc-notched-outline__trailing { border-color: rgba(0, 0, 0, 0.12); @@ -203,7 +212,7 @@ line-height: 20px; } } - .mat-mdc-form-field-icon-suffix { + .mat-mdc-form-field-icon-prefix, .mat-mdc-form-field-icon-suffix { height: 40px; font-size: 14px; line-height: 40px; @@ -336,4 +345,49 @@ } } } + + .tb-no-data-available { + flex: 1; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + } + + .tb-no-data-bg { + margin: 10px; + position: relative; + flex: 1; + width: 100%; + max-height: 100px; + &:before { + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: #305680; + -webkit-mask-image: url(/assets/home/no_data_folder_bg.svg); + -webkit-mask-repeat: no-repeat; + -webkit-mask-size: contain; + -webkit-mask-position: center; + mask-image: url(/assets/home/no_data_folder_bg.svg); + mask-repeat: no-repeat; + mask-size: contain; + mask-position: center; + } + } + + .tb-no-data-text { + font-weight: 500; + font-size: 14px; + line-height: 20px; + letter-spacing: 0.25px; + color: rgba(0, 0, 0, 0.54); + @media #{$mat-md-lg} { + font-size: 12px; + line-height: 16px; + } + } } From 25f0c9e15f7d04127a640a2d765b16eeb9d1621a Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Thu, 13 Jul 2023 12:48:21 +0300 Subject: [PATCH 18/22] UI: Minor improvements --- ui-ngx/src/app/core/services/utils.service.ts | 26 +++++++++++- .../lib/alarms-table-widget.component.ts | 40 ++++--------------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/ui-ngx/src/app/core/services/utils.service.ts b/ui-ngx/src/app/core/services/utils.service.ts index 339c1e1742..a6065dfe62 100644 --- a/ui-ngx/src/app/core/services/utils.service.ts +++ b/ui-ngx/src/app/core/services/utils.service.ts @@ -41,7 +41,7 @@ import { TranslateService } from '@ngx-translate/core'; import { customTranslationsPrefix, i18nPrefix } from '@app/shared/models/constants'; import { DataKey, Datasource, DatasourceType, KeyInfo } from '@shared/models/widget.models'; import { DataKeyType } from '@app/shared/models/telemetry/telemetry.models'; -import { alarmFields } from '@shared/models/alarm.models'; +import { alarmFields, alarmSeverityTranslations, alarmStatusTranslations } from '@shared/models/alarm.models'; import { materialColors } from '@app/shared/models/material.models'; import { WidgetInfo } from '@home/models/widget-component.models'; import jsonSchemaDefaults from 'json-schema-defaults'; @@ -55,6 +55,8 @@ import { TelemetryType } from '@shared/models/telemetry/telemetry.models'; import { EntityId } from '@shared/models/id/entity-id'; +import { DatePipe } from '@angular/common'; +import { entityTypeTranslations } from '@shared/models/entity-type.models'; const i18nRegExp = new RegExp(`{${i18nPrefix}:[^{}]+}`, 'g'); @@ -115,6 +117,7 @@ export class UtilsService { constructor(@Inject(WINDOW) private window: Window, private zone: NgZone, + private datePipe: DatePipe, private translate: TranslateService) { let frame: Element = null; try { @@ -170,6 +173,27 @@ export class UtilsService { return deepClone(this.defaultAlarmDataKeys); } + public defaultAlarmFieldContent(key: DataKey | {name: string}, value: any): string { + if (isDefined(value)) { + const alarmField = alarmFields[key.name]; + if (alarmField) { + if (alarmField.time) { + return value ? this.datePipe.transform(value, 'yyyy-MM-dd HH:mm:ss') : ''; + } else if (alarmField === alarmFields.severity) { + return this.translate.instant(alarmSeverityTranslations.get(value)); + } else if (alarmField === alarmFields.status) { + return alarmStatusTranslations.get(value) ? this.translate.instant(alarmStatusTranslations.get(value)) : value; + } else if (alarmField === alarmFields.originatorType) { + return this.translate.instant(entityTypeTranslations.get(value).type); + } else if (alarmField.value === alarmFields.assignee.value) { + return ''; + } + } + return value; + } + return ''; + } + public generateObjectFromJsonSchema(schema: any): any { const obj = jsonSchemaDefaults(schema); deleteNullProperties(obj); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/alarms-table-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/alarms-table-widget.component.ts index a0062645ac..db2d04ea88 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/alarms-table-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/alarms-table-widget.component.ts @@ -23,6 +23,7 @@ import { Injector, Input, NgZone, + OnDestroy, OnInit, StaticProvider, ViewChild, @@ -52,7 +53,6 @@ import { Direction } from '@shared/models/page/sort-order'; import { CollectionViewer, DataSource, SelectionModel } from '@angular/cdk/collections'; import { BehaviorSubject, forkJoin, fromEvent, merge, Observable, Subscription } from 'rxjs'; import { emptyPageData, PageData } from '@shared/models/page/page-data'; -import { entityTypeTranslations } from '@shared/models/entity-type.models'; import { debounceTime, distinctUntilChanged, map, take, tap } from 'rxjs/operators'; import { MatPaginator } from '@angular/material/paginator'; import { MatSort, SortDirection } from '@angular/material/sort'; @@ -92,15 +92,7 @@ import { DisplayColumnsPanelComponent, DisplayColumnsPanelData } from '@home/components/widget/lib/display-columns-panel.component'; -import { - AlarmDataInfo, - alarmFields, - AlarmInfo, - alarmSeverityColors, - alarmSeverityTranslations, - AlarmStatus, - alarmStatusTranslations -} from '@shared/models/alarm.models'; +import { AlarmDataInfo, alarmFields, AlarmInfo, alarmSeverityColors, AlarmStatus } from '@shared/models/alarm.models'; import { DatePipe } from '@angular/common'; import { AlarmDetailsDialogComponent, @@ -139,7 +131,6 @@ import { AlarmFilterConfigData } from '@home/components/alarm/alarm-filter-config.component'; import { getCurrentAuthUser } from '@core/auth/auth.selectors'; -import { UserId } from '@shared/models/id/user-id'; interface AlarmsTableWidgetSettings extends TableWidgetSettings { alarmsTitle: string; @@ -167,7 +158,7 @@ interface AlarmWidgetActionDescriptor extends TableCellButtonActionDescriptor { templateUrl: './alarms-table-widget.component.html', styleUrls: ['./alarms-table-widget.component.scss', './table-widget.scss'] }) -export class AlarmsTableWidgetComponent extends PageComponent implements OnInit, AfterViewInit { +export class AlarmsTableWidgetComponent extends PageComponent implements OnInit, OnDestroy, AfterViewInit { @Input() ctx: WidgetContext; @@ -431,7 +422,7 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit, keySettings.columnWidth = '120px'; } if (alarmField && alarmField.keyName === alarmFields.assignee.keyName) { - keySettings.columnWidth = '120px' + keySettings.columnWidth = '120px'; } } this.stylesInfo[dataKey.def] = getCellStyleInfo(keySettings, 'value, alarm, ctx'); @@ -543,14 +534,12 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit, overlayRef.dispose(); }); - const columns: DisplayColumn[] = this.columns.map(column => { - return { + const columns: DisplayColumn[] = this.columns.map(column => ({ title: column.title, def: column.def, display: this.displayedColumns.indexOf(column.def) > -1, selectable: this.columnSelectionAvailability[column.def] - }; - }); + })); const providers: StaticProvider[] = [ { @@ -1010,7 +999,7 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit, data: { alarmId: alarm.id.id } - }).afterClosed() + }).afterClosed(); } } @@ -1018,20 +1007,7 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit, if (isDefined(value)) { const alarmField = alarmFields[key.name]; if (alarmField) { - if (alarmField.time) { - return value ? this.datePipe.transform(value, 'yyyy-MM-dd HH:mm:ss') : ''; - } else if (alarmField.value === alarmFields.severity.value) { - return this.translate.instant(alarmSeverityTranslations.get(value)); - } else if (alarmField.value === alarmFields.status.value) { - return alarmStatusTranslations.get(value) ? this.translate.instant(alarmStatusTranslations.get(value)) : value; - } else if (alarmField.value === alarmFields.originatorType.value) { - return this.translate.instant(entityTypeTranslations.get(value).type); - } else if (alarmField.value === alarmFields.assignee.value) { - return ''; - } - else { - return value; - } + return this.utils.defaultAlarmFieldContent(key, value); } const entityField = entityFields[key.name]; if (entityField) { From b74e52d14ad730c1d752eab3e5439567aa3dca39 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Thu, 13 Jul 2023 18:14:50 +0300 Subject: [PATCH 19/22] UI: Improve color picker --- .../src/app/core/services/dialog.service.ts | 3 +- .../alarm/alarm-assignee.component.scss | 6 -- .../alarms-table-basic-config.component.html | 27 ++++----- ...entities-table-basic-config.component.html | 27 ++++----- .../simple-card-basic-config.component.html | 22 +++----- ...meseries-table-basic-config.component.html | 27 ++++----- .../chart/flot-basic-config.component.html | 27 ++++----- .../config/data-key-config.component.html | 11 ++-- .../widget/config/data-keys.component.html | 2 +- .../widget/config/data-keys.component.ts | 32 ++++++++--- .../chart/flot-key-settings.component.html | 11 ++-- .../flot-latest-key-settings.component.html | 11 ++-- .../chart/flot-widget-settings.component.html | 54 +++++++----------- .../widget/widget-config.component.html | 27 ++++----- .../components/color-input.component.html | 13 ++++- .../components/color-input.component.scss | 9 +++ .../components/color-input.component.ts | 42 +++++++++++++- .../color-picker-panel.component.html | 30 ++++++++++ .../color-picker-panel.component.scss | 36 ++++++++++++ .../color-picker-panel.component.ts | 55 +++++++++++++++++++ .../color-picker/color-picker.component.html | 14 ++++- .../color-picker/color-picker.component.scss | 39 ++++++++----- .../color-picker/color-picker.component.ts | 27 +++++---- .../dialog/color-picker-dialog.component.html | 30 ++++------ .../dialog/color-picker-dialog.component.scss | 22 ++++++++ .../dialog/color-picker-dialog.component.ts | 24 +++----- ui-ngx/src/app/shared/shared.module.ts | 3 + .../assets/locale/locale.constant-en_US.json | 3 + ui-ngx/src/form.scss | 53 +++++++++--------- 29 files changed, 423 insertions(+), 264 deletions(-) create mode 100644 ui-ngx/src/app/shared/components/color-picker/color-picker-panel.component.html create mode 100644 ui-ngx/src/app/shared/components/color-picker/color-picker-panel.component.scss create mode 100644 ui-ngx/src/app/shared/components/color-picker/color-picker-panel.component.ts create mode 100644 ui-ngx/src/app/shared/components/dialog/color-picker-dialog.component.scss diff --git a/ui-ngx/src/app/core/services/dialog.service.ts b/ui-ngx/src/app/core/services/dialog.service.ts index 1daf90ac82..2ca2d6d87e 100644 --- a/ui-ngx/src/app/core/services/dialog.service.ts +++ b/ui-ngx/src/app/core/services/dialog.service.ts @@ -103,7 +103,8 @@ export class DialogService { panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], data: { color - } + }, + autoFocus: false }).afterClosed(); } diff --git a/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee.component.scss b/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee.component.scss index 947eeb01d0..3aed0ccb5e 100644 --- a/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee.component.scss +++ b/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee.component.scss @@ -45,9 +45,3 @@ margin-right: 8px; } } - -.drop-down-icon { - &.inline { - margin-right: -12px; - } -} diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/alarm/alarms-table-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/alarm/alarms-table-basic-config.component.html index 90314b9cbe..18cd34609e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/alarm/alarms-table-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/alarm/alarms-table-basic-config.component.html @@ -58,16 +58,15 @@
-
+
{{ 'widget-config.card-icon' | translate }} -
+
- @@ -82,23 +81,17 @@ {{ 'fullscreen.fullscreen' | translate }}
-
+
{{ 'widget-config.text-color' | translate }}
-
- - - -
+ +
-
+
{{ 'widget-config.background-color' | translate }}
-
- - - -
+ +
-
+
{{ 'widget-config.card-icon' | translate }} -
+
- @@ -70,23 +69,17 @@ {{ 'fullscreen.fullscreen' | translate }}
-
+
{{ 'widget-config.text-color' | translate }}
-
- - - -
+ +
-
+
{{ 'widget-config.background-color' | translate }}
-
- - - -
+ +
{{ 'fullscreen.fullscreen' | translate }}
-
+
{{ 'widget-config.text-color' | translate }}
-
- - - -
+ +
-
+
{{ 'widget-config.background' | translate }}
-
- - - -
+ +
-
+
{{ 'widget-config.card-icon' | translate }} -
+
- @@ -70,23 +69,17 @@ {{ 'fullscreen.fullscreen' | translate }}
-
+
{{ 'widget-config.text-color' | translate }}
-
- - - -
+ +
-
+
{{ 'widget-config.background-color' | translate }}
-
- - - -
+ +
-
+
{{ 'widget-config.card-icon' | translate }} -
+
- @@ -68,23 +67,17 @@ {{ 'fullscreen.fullscreen' | translate }}
-
+
{{ 'widget-config.text-color' | translate }}
-
- - - -
+ +
-
+
{{ 'widget-config.background-color' | translate }}
-
- - - -
+ +
diff --git a/ui-ngx/src/app/modules/home/components/widget/config/data-key-config.component.html b/ui-ngx/src/app/modules/home/components/widget/config/data-key-config.component.html index a32735e0d1..8510e19f24 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/data-key-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/data-key-config.component.html @@ -59,14 +59,11 @@
-
+
{{ 'datakey.color' | translate }}
-
- - - -
+ +
diff --git a/ui-ngx/src/app/modules/home/components/widget/config/data-keys.component.html b/ui-ngx/src/app/modules/home/components/widget/config/data-keys.component.html index 39fffd79e7..65daa6552c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/data-keys.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/data-keys.component.html @@ -72,7 +72,7 @@
-
+
diff --git a/ui-ngx/src/app/modules/home/components/widget/config/data-keys.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/data-keys.component.ts index 95fe5bc444..02060db364 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/data-keys.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/data-keys.component.ts @@ -27,6 +27,7 @@ import { SimpleChanges, SkipSelf, ViewChild, + ViewContainerRef, ViewEncapsulation } from '@angular/core'; import { @@ -56,7 +57,6 @@ import { alarmFields } from '@shared/models/alarm.models'; import { UtilsService } from '@core/services/utils.service'; import { ErrorStateMatcher } from '@angular/material/core'; import { TruncatePipe } from '@shared/pipe/truncate.pipe'; -import { DialogService } from '@core/services/dialog.service'; import { MatDialog } from '@angular/material/dialog'; import { DataKeyConfigDialogComponent, @@ -69,6 +69,8 @@ import { DndDropEvent } from 'ngx-drag-drop/lib/dnd-dropzone.directive'; import { moveItemInArray } from '@angular/cdk/drag-drop'; import { coerceBoolean } from '@shared/decorators/coercion'; import { DatasourceComponent } from '@home/components/widget/config/datasource.component'; +import { ColorPickerPanelComponent } from '@shared/components/color-picker/color-picker-panel.component'; +import { TbPopoverService } from '@shared/components/popover.service'; @Component({ selector: 'tb-data-keys', @@ -208,10 +210,11 @@ export class DataKeysComponent implements ControlValueAccessor, OnInit, OnChange private datasourceComponent: DatasourceComponent, public translate: TranslateService, private utils: UtilsService, - private dialogs: DialogService, private dialog: MatDialog, private fb: UntypedFormBuilder, private cd: ChangeDetectorRef, + private popoverService: TbPopoverService, + private viewContainerRef: ViewContainerRef, private renderer: Renderer2, public truncate: TruncatePipe) { } @@ -471,15 +474,30 @@ export class DataKeysComponent implements ControlValueAccessor, OnInit, OnChange this.propagateChange(this.modelValue); } - showColorPicker(key: DataKey) { - this.dialogs.colorPicker(key.color).subscribe( - (color) => { + openColorPickerPopup(key: DataKey, $event: Event, keyColorButton: HTMLDivElement) { + if ($event) { + $event.stopPropagation(); + } + const trigger = keyColorButton; + if (this.popoverService.hasPopover(trigger)) { + this.popoverService.hidePopover(trigger); + } else { + const colorPickerPopover = this.popoverService.displayPopover(trigger, this.renderer, + this.viewContainerRef, ColorPickerPanelComponent, 'left', true, null, + { + color: key.color + }, + {}, + {}, {}, true); + colorPickerPopover.tbComponentRef.instance.popover = colorPickerPopover; + colorPickerPopover.tbComponentRef.instance.colorSelected.subscribe((color) => { + colorPickerPopover.hide(); if (color && key.color !== color) { key.color = color; this.propagateChange(this.modelValue); } - } - ); + }); + } } editDataKey(key: DataKey, index: number) { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-key-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-key-settings.component.html index f3176f9834..96ff4d8559 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-key-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-key-settings.component.html @@ -235,14 +235,11 @@
-
+
{{ 'widgets.chart.comparison-line-color' | translate }}
-
- - - -
+ +
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-latest-key-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-latest-key-settings.component.html index cdff37f492..286d26481b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-latest-key-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-latest-key-settings.component.html @@ -36,14 +36,11 @@ px
-
+
{{ 'widgets.chart.threshold-color' | translate }}
-
- - - -
+ +
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.html index defc26856a..5dd7eaa2dc 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.html @@ -61,14 +61,13 @@
-
+
{{ 'widgets.chart.default-font' | translate }}
-
+
px - @@ -132,14 +131,11 @@ -
+
{{ 'widget-config.color' | translate }}
-
- - - -
+ +
widget-config.decimals-short
@@ -187,14 +183,11 @@ -
+
{{ 'widget-config.color' | translate }}
-
- - - -
+ +
@@ -213,36 +206,29 @@ {{ 'widgets.chart.horizontal-grid-lines' | translate }}
-
+
{{ 'widgets.chart.grid-lines-color' | translate }}
-
- - - -
+ +
-
+
{{ 'widgets.chart.border' | translate }}
-
+
px -
-
+
{{ 'widgets.chart.background-color' | translate }}
-
- - - -
+ +
diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-config.component.html b/ui-ngx/src/app/modules/home/components/widget/widget-config.component.html index ab226987ca..68a9ed6f3d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/widget-config.component.html @@ -48,11 +48,11 @@
-
+
{{ 'widget-config.display-icon' | translate }} -
+
@@ -60,7 +60,6 @@ - @@ -84,23 +83,17 @@
widget-config.card-style
-
+
{{ 'widget-config.text-color' | translate }}
-
- - - -
+ +
-
+
{{ 'widget-config.background-color' | translate }}
-
- - - -
+ +
{{ 'widget-config.padding' | translate }}
diff --git a/ui-ngx/src/app/shared/components/color-input.component.html b/ui-ngx/src/app/shared/components/color-input.component.html index 2a283f7d93..c027104c6e 100644 --- a/ui-ngx/src/app/shared/components/color-input.component.html +++ b/ui-ngx/src/app/shared/components/color-input.component.html @@ -35,7 +35,14 @@ -
-
-
+
diff --git a/ui-ngx/src/app/shared/components/color-input.component.scss b/ui-ngx/src/app/shared/components/color-input.component.scss index ca8ffedc72..b81ac0fdf8 100644 --- a/ui-ngx/src/app/shared/components/color-input.component.scss +++ b/ui-ngx/src/app/shared/components/color-input.component.scss @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +@import './../../../scss/mixins'; + :host { .mat-mdc-form-field { width: 100%; @@ -29,4 +32,10 @@ margin: 0; } } + button.mat-mdc-button-base.color-box { + width: 40px; + min-width: 40px; + height: 40px; + padding: 7px; + } } diff --git a/ui-ngx/src/app/shared/components/color-input.component.ts b/ui-ngx/src/app/shared/components/color-input.component.ts index fa6c73116e..f22b91fde2 100644 --- a/ui-ngx/src/app/shared/components/color-input.component.ts +++ b/ui-ngx/src/app/shared/components/color-input.component.ts @@ -14,15 +14,24 @@ /// limitations under the License. /// -import { ChangeDetectorRef, Component, forwardRef, Input, OnInit } from '@angular/core'; +import { ChangeDetectorRef, Component, forwardRef, Input, OnInit, Renderer2, ViewContainerRef } from '@angular/core'; import { PageComponent } from '@shared/components/page.component'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; -import { ControlValueAccessor, UntypedFormBuilder, UntypedFormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; +import { + ControlValueAccessor, + NG_VALUE_ACCESSOR, + UntypedFormBuilder, + UntypedFormGroup, + Validators +} from '@angular/forms'; import { TranslateService } from '@ngx-translate/core'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { DialogService } from '@core/services/dialog.service'; import { coerceBoolean } from '@shared/decorators/coercion'; +import { TbPopoverService } from '@shared/components/popover.service'; +import { ColorPickerPanelComponent } from '@shared/components/color-picker/color-picker-panel.component'; +import { MatButton } from '@angular/material/button'; @Component({ selector: 'tb-color-input', @@ -100,6 +109,9 @@ export class ColorInputComponent extends PageComponent implements OnInit, Contro constructor(protected store: Store, private dialogs: DialogService, private translate: TranslateService, + private popoverService: TbPopoverService, + private renderer: Renderer2, + private viewContainerRef: ViewContainerRef, private fb: UntypedFormBuilder, private cd: ChangeDetectorRef) { super(store); @@ -167,6 +179,32 @@ export class ColorInputComponent extends PageComponent implements OnInit, Contro ); } + openColorPickerPopup($event: Event, matButton: MatButton) { + if ($event) { + $event.stopPropagation(); + } + const trigger = matButton._elementRef.nativeElement; + if (this.popoverService.hasPopover(trigger)) { + this.popoverService.hidePopover(trigger); + } else { + const colorPickerPopover = this.popoverService.displayPopover(trigger, this.renderer, + this.viewContainerRef, ColorPickerPanelComponent, 'left', true, null, + { + color: this.colorFormGroup.get('color').value + }, + {}, + {}, {}, true); + colorPickerPopover.tbComponentRef.instance.popover = colorPickerPopover; + colorPickerPopover.tbComponentRef.instance.colorSelected.subscribe((color) => { + colorPickerPopover.hide(); + this.colorFormGroup.patchValue( + {color}, {emitEvent: true} + ); + this.cd.markForCheck(); + }); + } + } + clear() { this.colorFormGroup.get('color').patchValue(null, {emitEvent: true}); this.cd.markForCheck(); diff --git a/ui-ngx/src/app/shared/components/color-picker/color-picker-panel.component.html b/ui-ngx/src/app/shared/components/color-picker/color-picker-panel.component.html new file mode 100644 index 0000000000..56e4523b67 --- /dev/null +++ b/ui-ngx/src/app/shared/components/color-picker/color-picker-panel.component.html @@ -0,0 +1,30 @@ + +
+
color.color
+ +
+ +
+
diff --git a/ui-ngx/src/app/shared/components/color-picker/color-picker-panel.component.scss b/ui-ngx/src/app/shared/components/color-picker/color-picker-panel.component.scss new file mode 100644 index 0000000000..e7d78b4018 --- /dev/null +++ b/ui-ngx/src/app/shared/components/color-picker/color-picker-panel.component.scss @@ -0,0 +1,36 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +.tb-color-picker-panel { + width: 328px; + display: flex; + flex-direction: column; + gap: 16px; + .tb-color-picker-title { + font-size: 16px; + font-weight: 500; + line-height: 24px; + letter-spacing: 0.25px; + color: rgba(0, 0, 0, 0.87); + } + .tb-color-picker-panel-buttons { + height: 60px; + display: flex; + flex-direction: row; + gap: 16px; + justify-content: flex-end; + align-items: flex-end; + } +} diff --git a/ui-ngx/src/app/shared/components/color-picker/color-picker-panel.component.ts b/ui-ngx/src/app/shared/components/color-picker/color-picker-panel.component.ts new file mode 100644 index 0000000000..59199388b8 --- /dev/null +++ b/ui-ngx/src/app/shared/components/color-picker/color-picker-panel.component.ts @@ -0,0 +1,55 @@ +/// +/// Copyright © 2016-2023 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { PageComponent } from '@shared/components/page.component'; +import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { UntypedFormControl } from '@angular/forms'; +import { TbPopoverComponent } from '@shared/components/popover.component'; + +@Component({ + selector: 'tb-color-picker-panel', + templateUrl: './color-picker-panel.component.html', + providers: [], + styleUrls: ['./color-picker-panel.component.scss'], + encapsulation: ViewEncapsulation.None +}) +export class ColorPickerPanelComponent extends PageComponent implements OnInit { + + @Input() + color: string; + + @Input() + popover: TbPopoverComponent; + + @Output() + colorSelected = new EventEmitter(); + + colorPickerControl: UntypedFormControl; + + constructor(protected store: Store) { + super(store); + } + + ngOnInit(): void { + this.colorPickerControl = new UntypedFormControl(this.color); + } + + selectColor() { + this.colorSelected.emit(this.colorPickerControl.value); + } +} diff --git a/ui-ngx/src/app/shared/components/color-picker/color-picker.component.html b/ui-ngx/src/app/shared/components/color-picker/color-picker.component.html index d1432d27f5..5806037c89 100644 --- a/ui-ngx/src/app/shared/components/color-picker/color-picker.component.html +++ b/ui-ngx/src/app/shared/components/color-picker/color-picker.component.html @@ -19,7 +19,7 @@
@@ -29,7 +29,12 @@
-
+ + HEX + RGBA + HSLA + +
-
+
+ +
+
diff --git a/ui-ngx/src/app/shared/components/color-picker/color-picker.component.scss b/ui-ngx/src/app/shared/components/color-picker/color-picker.component.scss index ea2bfa94ba..dc1d3b5042 100644 --- a/ui-ngx/src/app/shared/components/color-picker/color-picker.component.scss +++ b/ui-ngx/src/app/shared/components/color-picker/color-picker.component.scss @@ -17,12 +17,10 @@ width: 100%; display: flex; flex-direction: column; - gap: 16px; + gap: 32px; .saturation-component { - height: 100%; - min-height: 200px; - max-height: 300px; + height: 238px; border-radius: 8px; } @@ -55,6 +53,12 @@ .color-input-block { display: flex; + gap: 20px; + + .presentation-select { + font-size: 14px; + width: 56px; + } .color-input { flex: 1; @@ -63,16 +67,13 @@ color: initial; } } + } - .type-btn { - height: 26px; - width: 20px; - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAgCAMAAAAootjDAAAAM1BMVEUAAAAzMzMzMzMzMzMzMzM0NDQzMzMzMzM0NDQzMzMzMzM0NDQzMzMzMzMyMjIrKyszMzPF8UZlAAAAEHRSTlMA1fHr4ZxxSRP45sG+sCkGH2+Z6QAAAHJJREFUKM+9kkkSgCAQA0FEVLb5/2tViqgQvNrHviSzKGCt6nDGuNass8i8NsrLiX+bZbrUtDwm7VLYE0zWUtEZ+RvUZpEvN8YhH9QmQRoC8kFpEnVHVP/DJUZVeSAem5fDKxwtms/BR+PT8gN8vwk/0wE1gQzNVYryIwAAAABJRU5ErkJggg==') no-repeat center; - background-size: 6px 12px; - - &:hover { - background-color: #eee; - } + .color-presets-block { + .color-presets-component { + display: flex; + flex-direction: column; + gap: 12px; } } } @@ -105,4 +106,16 @@ } } } + + .color-presets-component { + .presets-row { + gap: 10px; + justify-content: space-between; + } + color-preset { + height: 20px; + width: 20px; + border-radius: 4px; + } + } } diff --git a/ui-ngx/src/app/shared/components/color-picker/color-picker.component.ts b/ui-ngx/src/app/shared/components/color-picker/color-picker.component.ts index ce49310b03..47a745819d 100644 --- a/ui-ngx/src/app/shared/components/color-picker/color-picker.component.ts +++ b/ui-ngx/src/app/shared/components/color-picker/color-picker.component.ts @@ -17,7 +17,7 @@ import { Component, forwardRef, OnDestroy } from '@angular/core'; import { Color, ColorPickerControl } from '@iplab/ngx-color-picker'; import { Subscription } from 'rxjs'; -import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; +import { ControlValueAccessor, NG_VALUE_ACCESSOR, UntypedFormControl } from '@angular/forms'; export enum ColorType { hex = 'hex', @@ -29,6 +29,10 @@ export enum ColorType { cmyk = 'cmyk' } +const colorPresetsHex = + ['#435B63', '#F44336', '#E89623', '#F5DD00', '#8BC34A', '#4CAF50', '#009688', '#048AD3', '#673AB7', '#9C27B0', '#E91E63', + '#A1ADB1', '#F9A19B', '#FFD190', '#FFF59D', '#C5E1A4', '#A5D7A7', '#80CBC3', '#81C4E9', '#B39CDB', '#CD93D7', '#F48FB1']; + @Component({ selector: `tb-color-picker`, templateUrl: `./color-picker.component.html`, @@ -43,10 +47,13 @@ export enum ColorType { }) export class ColorPickerComponent implements ControlValueAccessor, OnDestroy { - selectedPresentation = 0; presentations = [ColorType.hex, ColorType.rgba, ColorType.hsla]; control = new ColorPickerControl(); + presentationControl = new UntypedFormControl(0); + + colorPresets: Color[] = colorPresetsHex.map(c => Color.from(c)); + private modelValue: string; private subscriptions: Array = []; @@ -65,6 +72,11 @@ export class ColorPickerComponent implements ControlValueAccessor, OnDestroy { } }) ); + this.subscriptions.push( + this.presentationControl.valueChanges.subscribe(() => { + this.updateModel(); + }) + ); } registerOnChange(fn: any): void { @@ -86,12 +98,11 @@ export class ColorPickerComponent implements ControlValueAccessor, OnDestroy { } else if (this.control.initType === ColorType.hsl) { this.control.initType = ColorType.hsla; } - - this.selectedPresentation = this.presentations.indexOf(this.control.initType); + this.presentationControl.patchValue(this.presentations.indexOf(this.control.initType), {emitEvent: false}); } private updateModel() { - const color: string = this.getValueByType(this.control.value, this.presentations[this.selectedPresentation]); + const color: string = this.getValueByType(this.control.value, this.presentations[this.presentationControl.value]); if (this.modelValue !== color) { this.modelValue = color; this.propagateChange(color); @@ -103,12 +114,6 @@ export class ColorPickerComponent implements ControlValueAccessor, OnDestroy { this.subscriptions.length = 0; } - public changePresentation(): void { - this.selectedPresentation = - this.selectedPresentation === this.presentations.length - 1 ? 0 : this.selectedPresentation + 1; - this.updateModel(); - } - getValueByType(color: Color, type: ColorType): string { switch (type) { case ColorType.hex: diff --git a/ui-ngx/src/app/shared/components/dialog/color-picker-dialog.component.html b/ui-ngx/src/app/shared/components/dialog/color-picker-dialog.component.html index eaec4c0b5e..0d916f428a 100644 --- a/ui-ngx/src/app/shared/components/dialog/color-picker-dialog.component.html +++ b/ui-ngx/src/app/shared/components/dialog/color-picker-dialog.component.html @@ -15,22 +15,14 @@ limitations under the License. --> -
-
- -
-
- - - -
-
+
+ + + +
diff --git a/ui-ngx/src/app/shared/components/dialog/color-picker-dialog.component.scss b/ui-ngx/src/app/shared/components/dialog/color-picker-dialog.component.scss new file mode 100644 index 0000000000..afd8d1cfcb --- /dev/null +++ b/ui-ngx/src/app/shared/components/dialog/color-picker-dialog.component.scss @@ -0,0 +1,22 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +:host { + .tb-close-button { + position: absolute; + top: 6px; + right: 6px; + } +} diff --git a/ui-ngx/src/app/shared/components/dialog/color-picker-dialog.component.ts b/ui-ngx/src/app/shared/components/dialog/color-picker-dialog.component.ts index 44959023f4..219ed0ec56 100644 --- a/ui-ngx/src/app/shared/components/dialog/color-picker-dialog.component.ts +++ b/ui-ngx/src/app/shared/components/dialog/color-picker-dialog.component.ts @@ -14,11 +14,10 @@ /// limitations under the License. /// -import { Component, Inject, OnInit } from '@angular/core'; +import { Component, Inject } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Router } from '@angular/router'; import { DialogComponent } from '@shared/components/dialog.component'; @@ -29,33 +28,26 @@ export interface ColorPickerDialogData { @Component({ selector: 'tb-color-picker-dialog', templateUrl: './color-picker-dialog.component.html', - styleUrls: [] + styleUrls: ['./color-picker-dialog.component.scss'] }) -export class ColorPickerDialogComponent extends DialogComponent - implements OnInit { +export class ColorPickerDialogComponent extends DialogComponent { - colorPickerFormGroup: FormGroup; + color: string; constructor(protected store: Store, protected router: Router, @Inject(MAT_DIALOG_DATA) public data: ColorPickerDialogData, - public dialogRef: MatDialogRef, - public fb: FormBuilder) { + public dialogRef: MatDialogRef) { super(store, router, dialogRef); + this.color = data.color; } - ngOnInit(): void { - this.colorPickerFormGroup = this.fb.group({ - color: [this.data.color, [Validators.required]] - }); + selectColor(color: string) { + this.dialogRef.close(color); } cancel(): void { this.dialogRef.close(null); } - select(): void { - const color: string = this.colorPickerFormGroup.get('color').value; - this.dialogRef.close(color); - } } diff --git a/ui-ngx/src/app/shared/shared.module.ts b/ui-ngx/src/app/shared/shared.module.ts index 25eee9ca08..11c4b4effb 100644 --- a/ui-ngx/src/app/shared/shared.module.ts +++ b/ui-ngx/src/app/shared/shared.module.ts @@ -196,6 +196,7 @@ import { RuleChainSelectComponent } from '@shared/components/rule-chain/rule-cha import { ToggleSelectComponent } from '@shared/components/toggle-select.component'; import { UnitInputComponent } from '@shared/components/unit-input.component'; import { MaterialIconsComponent } from '@shared/components/material-icons.component'; +import { ColorPickerPanelComponent } from '@shared/components/color-picker/color-picker-panel.component'; export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService) { return markedOptionsService; @@ -365,6 +366,7 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService) GtMdLgLayoutGapDirective, GtMdLgShowHideDirective, ColorPickerComponent, + ColorPickerPanelComponent, ResourceAutocompleteComponent, ToggleHeaderComponent, ToggleOption, @@ -597,6 +599,7 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService) GtMdLgLayoutGapDirective, GtMdLgShowHideDirective, ColorPickerComponent, + ColorPickerPanelComponent, ResourceAutocompleteComponent, ToggleHeaderComponent, ToggleOption, diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index bc3351aa83..cd379fa4dc 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -5500,6 +5500,9 @@ } } }, + "color": { + "color": "Color" + }, "icon": { "icon": "Icon", "icons": "Icons", diff --git a/ui-ngx/src/form.scss b/ui-ngx/src/form.scss index 8197e32f6c..c9e3bc6a16 100644 --- a/ui-ngx/src/form.scss +++ b/ui-ngx/src/form.scss @@ -131,14 +131,11 @@ } .tb-form-row { height: 100%; - padding-top: 7px; - padding-bottom: 7px; display: flex; flex-direction: row; align-items: center; gap: 16px; - padding-left: 16px; - padding-right: 12px; + padding: 7px 7px 7px 16px; border: 1px solid rgba(0, 0, 0, 0.12); border-radius: 6px; &.same-padding { @@ -314,33 +311,33 @@ .tb-prompt { height: 38px; } + } - .tb-form-table-row { - height: 38px; - display: flex; - flex-direction: row; - gap: 12px; - padding-left: 12px; + .tb-form-table-row { + height: 38px; + display: flex; + flex-direction: row; + gap: 12px; + padding-left: 12px; - &.tb-draggable { - gap: 0; - padding-left: 0; - background: #fff; - } + &.tb-draggable { + gap: 0; + padding-left: 0; + background: #fff; + } - &-cell-buttons { - display: flex; - flex-direction: row; - button.mat-mdc-icon-button.mat-mdc-button-base { - padding: 7px; - width: 38px; - height: 38px; - .mat-icon { - color: rgba(0, 0, 0, 0.38); - } - &.tb-hidden { - visibility: hidden; - } + &-cell-buttons { + display: flex; + flex-direction: row; + button.mat-mdc-icon-button.mat-mdc-button-base { + padding: 7px; + width: 38px; + height: 38px; + .mat-icon { + color: rgba(0, 0, 0, 0.38); + } + &.tb-hidden { + visibility: hidden; } } } From a9b8a6459e449beb995f0d16d15f31145331988b Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Thu, 13 Jul 2023 20:04:25 +0300 Subject: [PATCH 20/22] UI: Load home dashboards from asset resources --- .../home-links/home-links-routing.module.ts | 43 ++++++++++--------- .../dashboard/customer_user_home_page.json} | 0 .../dashboard/sys_admin_home_page.json} | 0 .../dashboard/tenant_admin_home_page.json} | 0 4 files changed, 22 insertions(+), 21 deletions(-) rename ui-ngx/src/{app/modules/home/pages/home-links/customer_user_home_page.raw => assets/dashboard/customer_user_home_page.json} (100%) rename ui-ngx/src/{app/modules/home/pages/home-links/sys_admin_home_page.raw => assets/dashboard/sys_admin_home_page.json} (100%) rename ui-ngx/src/{app/modules/home/pages/home-links/tenant_admin_home_page.raw => assets/dashboard/tenant_admin_home_page.json} (100%) diff --git a/ui-ngx/src/app/modules/home/pages/home-links/home-links-routing.module.ts b/ui-ngx/src/app/modules/home/pages/home-links/home-links-routing.module.ts index 5edc9cb7fc..c1c1c9bc9e 100644 --- a/ui-ngx/src/app/modules/home/pages/home-links/home-links-routing.module.ts +++ b/ui-ngx/src/app/modules/home/pages/home-links/home-links-routing.module.ts @@ -25,20 +25,19 @@ import { DashboardService } from '@core/http/dashboard.service'; import { select, Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { map } from 'rxjs/operators'; -import { - getCurrentAuthUser, - selectHasRepository, - selectPersistDeviceStateToTelemetry -} from '@core/auth/auth.selectors'; -import sysAdminHomePageDashboardJson from '!raw-loader!./sys_admin_home_page.raw'; -import tenantAdminHomePageDashboardJson from '!raw-loader!./tenant_admin_home_page.raw'; -import customerUserHomePageDashboardJson from '!raw-loader!./customer_user_home_page.raw'; +import { getCurrentAuthUser, selectPersistDeviceStateToTelemetry } from '@core/auth/auth.selectors'; import { EntityKeyType } from '@shared/models/query/query.models'; +import { ResourcesService } from '@core/services/resources.service'; + +const sysAdminHomePageJson = '/assets/dashboard/sys_admin_home_page.json'; +const tenantAdminHomePageJson = '/assets/dashboard/tenant_admin_home_page.json'; +const customerUserHomePageJson = '/assets/dashboard/customer_user_home_page.json'; @Injectable() export class HomeDashboardResolver implements Resolve { constructor(private dashboardService: DashboardService, + private resourcesService: ResourcesService, private store: Store) { } @@ -50,13 +49,13 @@ export class HomeDashboardResolver implements Resolve { const authority = getCurrentAuthUser(this.store).authority; switch (authority) { case Authority.SYS_ADMIN: - dashboard$ = of(JSON.parse(sysAdminHomePageDashboardJson)); + dashboard$ = this.resourcesService.loadJsonResource(sysAdminHomePageJson); break; case Authority.TENANT_ADMIN: - dashboard$ = this.updateDeviceActivityKeyFilterIfNeeded(JSON.parse(tenantAdminHomePageDashboardJson)); + dashboard$ = this.updateDeviceActivityKeyFilterIfNeeded(this.resourcesService.loadJsonResource(tenantAdminHomePageJson)); break; case Authority.CUSTOMER_USER: - dashboard$ = this.updateDeviceActivityKeyFilterIfNeeded(JSON.parse(customerUserHomePageDashboardJson)); + dashboard$ = this.updateDeviceActivityKeyFilterIfNeeded(this.resourcesService.loadJsonResource(customerUserHomePageJson)); break; } if (dashboard$) { @@ -73,18 +72,20 @@ export class HomeDashboardResolver implements Resolve { ); } - private updateDeviceActivityKeyFilterIfNeeded(dashboard: HomeDashboard): Observable { + private updateDeviceActivityKeyFilterIfNeeded(dashboard$: Observable): Observable { return this.store.pipe(select(selectPersistDeviceStateToTelemetry)).pipe( - map((persistToTelemetry) => { - if (persistToTelemetry) { - for (const filterId of Object.keys(dashboard.configuration.filters)) { - if (['Active Devices', 'Inactive Devices'].includes(dashboard.configuration.filters[filterId].filter)) { - dashboard.configuration.filters[filterId].keyFilters[0].key.type = EntityKeyType.TIME_SERIES; + mergeMap((persistToTelemetry) => dashboard$.pipe( + map((dashboard) => { + if (persistToTelemetry) { + for (const filterId of Object.keys(dashboard.configuration.filters)) { + if (['Active Devices', 'Inactive Devices'].includes(dashboard.configuration.filters[filterId].filter)) { + dashboard.configuration.filters[filterId].keyFilters[0].key.type = EntityKeyType.TIME_SERIES; + } + } } - } - } - return dashboard; - }) + return dashboard; + }) + )) ); } } diff --git a/ui-ngx/src/app/modules/home/pages/home-links/customer_user_home_page.raw b/ui-ngx/src/assets/dashboard/customer_user_home_page.json similarity index 100% rename from ui-ngx/src/app/modules/home/pages/home-links/customer_user_home_page.raw rename to ui-ngx/src/assets/dashboard/customer_user_home_page.json diff --git a/ui-ngx/src/app/modules/home/pages/home-links/sys_admin_home_page.raw b/ui-ngx/src/assets/dashboard/sys_admin_home_page.json similarity index 100% rename from ui-ngx/src/app/modules/home/pages/home-links/sys_admin_home_page.raw rename to ui-ngx/src/assets/dashboard/sys_admin_home_page.json diff --git a/ui-ngx/src/app/modules/home/pages/home-links/tenant_admin_home_page.raw b/ui-ngx/src/assets/dashboard/tenant_admin_home_page.json similarity index 100% rename from ui-ngx/src/app/modules/home/pages/home-links/tenant_admin_home_page.raw rename to ui-ngx/src/assets/dashboard/tenant_admin_home_page.json From 1033dce21ca23bdac2a23d4f7850b9268e2358cb Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Fri, 14 Jul 2023 13:54:43 +0300 Subject: [PATCH 21/22] UI: Move API usage dashboard to assets. Update deprecated dashboards resolvers by resolver functions. --- .../api-usage/api-usage-routing.module.ts | 18 ++- .../pages/api-usage/api-usage.component.ts | 16 +-- .../home-links/home-links-routing.module.ts | 111 ++++++++---------- .../dashboard/api_usage.json} | 0 4 files changed, 74 insertions(+), 71 deletions(-) rename ui-ngx/src/{app/modules/home/pages/api-usage/api_usage_json.raw => assets/dashboard/api_usage.json} (100%) diff --git a/ui-ngx/src/app/modules/home/pages/api-usage/api-usage-routing.module.ts b/ui-ngx/src/app/modules/home/pages/api-usage/api-usage-routing.module.ts index a38fbf9958..7d4bb5fe14 100644 --- a/ui-ngx/src/app/modules/home/pages/api-usage/api-usage-routing.module.ts +++ b/ui-ngx/src/app/modules/home/pages/api-usage/api-usage-routing.module.ts @@ -14,10 +14,21 @@ /// limitations under the License. /// -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; +import { inject, NgModule } from '@angular/core'; +import { ActivatedRouteSnapshot, ResolveFn, RouterModule, RouterStateSnapshot, Routes } from '@angular/router'; import { Authority } from '@shared/models/authority.enum'; import { ApiUsageComponent } from '@home/pages/api-usage/api-usage.component'; +import { Dashboard } from '@shared/models/dashboard.models'; +import { ResourcesService } from '@core/services/resources.service'; +import { Observable } from 'rxjs'; + +const apiUsageDashboardJson = '/assets/dashboard/api_usage.json'; + +export const apiUsageDashboardResolver: ResolveFn = ( + route: ActivatedRouteSnapshot, + state: RouterStateSnapshot, + resourcesService = inject(ResourcesService) +): Observable => resourcesService.loadJsonResource(apiUsageDashboardJson); const routes: Routes = [ { @@ -30,6 +41,9 @@ const routes: Routes = [ label: 'api-usage.api-usage', icon: 'insert_chart' } + }, + resolve: { + apiUsageDashboard: apiUsageDashboardResolver } } ]; diff --git a/ui-ngx/src/app/modules/home/pages/api-usage/api-usage.component.ts b/ui-ngx/src/app/modules/home/pages/api-usage/api-usage.component.ts index 0bcae0801b..e84a23fb66 100644 --- a/ui-ngx/src/app/modules/home/pages/api-usage/api-usage.component.ts +++ b/ui-ngx/src/app/modules/home/pages/api-usage/api-usage.component.ts @@ -14,28 +14,24 @@ /// limitations under the License. /// -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { PageComponent } from '@shared/components/page.component'; -import apiUsageDashboardJson from '!raw-loader!./api_usage_json.raw'; import { Dashboard } from '@shared/models/dashboard.models'; +import { ActivatedRoute } from '@angular/router'; @Component({ selector: 'tb-api-usage', templateUrl: './api-usage.component.html', styleUrls: ['./api-usage.component.scss'] }) -export class ApiUsageComponent extends PageComponent implements OnInit { +export class ApiUsageComponent extends PageComponent { - apiUsageDashboard: Dashboard; + apiUsageDashboard: Dashboard = this.route.snapshot.data.apiUsageDashboard; - constructor(protected store: Store) { + constructor(protected store: Store, + private route: ActivatedRoute) { super(store); } - - ngOnInit() { - this.apiUsageDashboard = JSON.parse(apiUsageDashboardJson); - } - } diff --git a/ui-ngx/src/app/modules/home/pages/home-links/home-links-routing.module.ts b/ui-ngx/src/app/modules/home/pages/home-links/home-links-routing.module.ts index c1c1c9bc9e..a11ae14231 100644 --- a/ui-ngx/src/app/modules/home/pages/home-links/home-links-routing.module.ts +++ b/ui-ngx/src/app/modules/home/pages/home-links/home-links-routing.module.ts @@ -14,8 +14,8 @@ /// limitations under the License. /// -import { Injectable, NgModule } from '@angular/core'; -import { Resolve, RouterModule, Routes } from '@angular/router'; +import { inject, NgModule } from '@angular/core'; +import { ActivatedRouteSnapshot, ResolveFn, RouterModule, RouterStateSnapshot, Routes } from '@angular/router'; import { HomeLinksComponent } from './home-links.component'; import { Authority } from '@shared/models/authority.enum'; @@ -33,62 +33,58 @@ const sysAdminHomePageJson = '/assets/dashboard/sys_admin_home_page.json'; const tenantAdminHomePageJson = '/assets/dashboard/tenant_admin_home_page.json'; const customerUserHomePageJson = '/assets/dashboard/customer_user_home_page.json'; -@Injectable() -export class HomeDashboardResolver implements Resolve { - - constructor(private dashboardService: DashboardService, - private resourcesService: ResourcesService, - private store: Store) { - } - - resolve(): Observable { - return this.dashboardService.getHomeDashboard().pipe( - mergeMap((dashboard) => { - if (!dashboard) { - let dashboard$: Observable; - const authority = getCurrentAuthUser(this.store).authority; - switch (authority) { - case Authority.SYS_ADMIN: - dashboard$ = this.resourcesService.loadJsonResource(sysAdminHomePageJson); - break; - case Authority.TENANT_ADMIN: - dashboard$ = this.updateDeviceActivityKeyFilterIfNeeded(this.resourcesService.loadJsonResource(tenantAdminHomePageJson)); - break; - case Authority.CUSTOMER_USER: - dashboard$ = this.updateDeviceActivityKeyFilterIfNeeded(this.resourcesService.loadJsonResource(customerUserHomePageJson)); - break; - } - if (dashboard$) { - return dashboard$.pipe( - map((homeDashboard) => { - homeDashboard.hideDashboardToolbar = true; - return homeDashboard; - }) - ); +const updateDeviceActivityKeyFilterIfNeeded = (store: Store, + dashboard$: Observable): Observable => + store.pipe(select(selectPersistDeviceStateToTelemetry)).pipe( + mergeMap((persistToTelemetry) => dashboard$.pipe( + map((dashboard) => { + if (persistToTelemetry) { + for (const filterId of Object.keys(dashboard.configuration.filters)) { + if (['Active Devices', 'Inactive Devices'].includes(dashboard.configuration.filters[filterId].filter)) { + dashboard.configuration.filters[filterId].keyFilters[0].key.type = EntityKeyType.TIME_SERIES; + } } } - return of(dashboard); + return dashboard; }) - ); - } + )) + ); - private updateDeviceActivityKeyFilterIfNeeded(dashboard$: Observable): Observable { - return this.store.pipe(select(selectPersistDeviceStateToTelemetry)).pipe( - mergeMap((persistToTelemetry) => dashboard$.pipe( - map((dashboard) => { - if (persistToTelemetry) { - for (const filterId of Object.keys(dashboard.configuration.filters)) { - if (['Active Devices', 'Inactive Devices'].includes(dashboard.configuration.filters[filterId].filter)) { - dashboard.configuration.filters[filterId].keyFilters[0].key.type = EntityKeyType.TIME_SERIES; - } - } - } - return dashboard; - }) - )) - ); - } -} +export const homeDashboardResolver: ResolveFn = ( + route: ActivatedRouteSnapshot, + state: RouterStateSnapshot, + dashboardService = inject(DashboardService), + resourcesService = inject(ResourcesService), + store: Store = inject(Store) +): Observable => + dashboardService.getHomeDashboard().pipe( + mergeMap((dashboard) => { + if (!dashboard) { + let dashboard$: Observable; + const authority = getCurrentAuthUser(store).authority; + switch (authority) { + case Authority.SYS_ADMIN: + dashboard$ = resourcesService.loadJsonResource(sysAdminHomePageJson); + break; + case Authority.TENANT_ADMIN: + dashboard$ = updateDeviceActivityKeyFilterIfNeeded(store, resourcesService.loadJsonResource(tenantAdminHomePageJson)); + break; + case Authority.CUSTOMER_USER: + dashboard$ = updateDeviceActivityKeyFilterIfNeeded(store, resourcesService.loadJsonResource(customerUserHomePageJson)); + break; + } + if (dashboard$) { + return dashboard$.pipe( + map((homeDashboard) => { + homeDashboard.hideDashboardToolbar = true; + return homeDashboard; + }) + ); + } + } + return of(dashboard); + }) + ); const routes: Routes = [ { @@ -103,16 +99,13 @@ const routes: Routes = [ } }, resolve: { - homeDashboard: HomeDashboardResolver + homeDashboard: homeDashboardResolver } } ]; @NgModule({ imports: [RouterModule.forChild(routes)], - exports: [RouterModule], - providers: [ - HomeDashboardResolver - ] + exports: [RouterModule] }) export class HomeLinksRoutingModule { } diff --git a/ui-ngx/src/app/modules/home/pages/api-usage/api_usage_json.raw b/ui-ngx/src/assets/dashboard/api_usage.json similarity index 100% rename from ui-ngx/src/app/modules/home/pages/api-usage/api_usage_json.raw rename to ui-ngx/src/assets/dashboard/api_usage.json From e557a2d2c4cc779135ff4946d79845d9762c633b Mon Sep 17 00:00:00 2001 From: rusikv Date: Fri, 14 Jul 2023 18:59:20 +0300 Subject: [PATCH 22/22] Refactoring --- .../components/details-panel.component.ts | 5 ++- .../components/event/event-table-config.ts | 2 +- .../rulechain/rule-node-config.component.ts | 16 ++++++++++ .../rule-node-details.component.html | 3 +- .../rulechain/rule-node-details.component.ts | 3 ++ .../rulechain/rulechain-page.component.html | 3 +- .../rulechain/rulechain-page.component.ts | 31 +++++++++---------- .../src/app/shared/models/rule-node.models.ts | 20 +++++------- 8 files changed, 48 insertions(+), 35 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/details-panel.component.ts b/ui-ngx/src/app/modules/home/components/details-panel.component.ts index 66facf08d4..b2f8a059f3 100644 --- a/ui-ngx/src/app/modules/home/components/details-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/details-panel.component.ts @@ -15,6 +15,7 @@ /// import { + ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, @@ -55,9 +56,7 @@ export class DetailsPanelComponent extends PageComponent implements OnDestroy { } this.theFormValue = value; if (this.theFormValue !== null) { - this.formSubscription = this.theFormValue.valueChanges.subscribe(() => { - this.cd.detectChanges() - }); + this.formSubscription = this.theFormValue.valueChanges.subscribe(() => this.cd.detectChanges()); } } } diff --git a/ui-ngx/src/app/modules/home/components/event/event-table-config.ts b/ui-ngx/src/app/modules/home/components/event/event-table-config.ts index 565dbf14bf..4021d018ce 100644 --- a/ui-ngx/src/app/modules/home/components/event/event-table-config.ts +++ b/ui-ngx/src/app/modules/home/components/event/event-table-config.ts @@ -359,7 +359,7 @@ export class EventTableConfig extends EntityTableConfig { case DebugEventType.DEBUG_RULE_NODE: if (this.testButtonLabel) { this.cellActionDescriptors.push({ - name: this.translate.instant('rulenode.test-with-this-message', {test: this.testButtonLabel}), + name: this.translate.instant('rulenode.test-with-this-message', {test: this.translate.instant(this.testButtonLabel)}), icon: 'bug_report', isEnabled: (entity) => entity.body.type === 'IN', onAction: ($event, entity) => { diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts index 6c19507301..3f3071221e 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts @@ -87,6 +87,9 @@ export class RuleNodeConfigComponent implements ControlValueAccessor, OnInit, On @Output() initRuleNode = new EventEmitter(); + @Output() + changeScript = new EventEmitter(); + nodeDefinitionValue: RuleNodeDefinition; @Input() @@ -110,6 +113,8 @@ export class RuleNodeConfigComponent implements ControlValueAccessor, OnInit, On changeSubscription: Subscription; + changeScriptSubscription: Subscription; + definedConfigComponent: IRuleNodeConfigurationComponent; private definedConfigComponentRef: ComponentRef; @@ -140,6 +145,14 @@ export class RuleNodeConfigComponent implements ControlValueAccessor, OnInit, On if (this.definedConfigComponentRef) { this.definedConfigComponentRef.destroy(); } + if (this.changeSubscription) { + this.changeSubscription.unsubscribe(); + this.changeSubscription = null; + } + if (this.changeScriptSubscription) { + this.changeScriptSubscription.unsubscribe(); + this.changeScriptSubscription = null; + } } ngAfterViewInit(): void { @@ -212,6 +225,9 @@ export class RuleNodeConfigComponent implements ControlValueAccessor, OnInit, On this.changeSubscription = this.definedConfigComponent.configurationChanged.subscribe((configuration) => { this.updateModel(configuration); }); + if (this.definedConfigComponent?.changeScript) { + this.changeScriptSubscription = this.definedConfigComponent.changeScript.subscribe(() => this.changeScript.emit()); + } } } diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.html b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.html index 2f925ded60..34aa8167e3 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.html +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.html @@ -51,7 +51,8 @@ [ruleChainId]="ruleChainId" [ruleChainType]="ruleChainType" [nodeDefinition]="ruleNode.component.configurationDescriptor.nodeDefinition" - (initRuleNode)="initRuleNode.emit($event)"> + (initRuleNode)="initRuleNode.emit($event)" + (changeScript)="changeScript.emit($event)">
diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.ts index 7b0f426c35..f1d6001c88 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.ts @@ -58,6 +58,9 @@ export class RuleNodeDetailsComponent extends PageComponent implements OnInit, O @Output() initRuleNode = new EventEmitter(); + @Output() + changeScript = new EventEmitter(); + ruleNodeType = RuleNodeType; entityType = EntityType; diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.html b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.html index ba91b45f16..5f5594cc1a 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.html +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.html @@ -112,7 +112,8 @@ [ruleChainType]="ruleChainType" [isEdit]="true" [isReadOnly]="false" - (initRuleNode)="onRuleNodeInit()"> + (initRuleNode)="onRuleNodeInit()" + (changeScript)="switchToFirstTab()"> diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts index d5ea093721..6b78d94ac7 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts @@ -1279,25 +1279,24 @@ export class RuleChainPageComponent extends PageComponent } onDebugEventSelected(debugEventBody: DebugRuleNodeEventBody) { - if (this.ruleNodeComponent.ruleNodeConfigComponent.useDefinedDirective() && - this.ruleNodeComponent.ruleNodeConfigComponent.definedConfigComponent.getSupportTestFunction() && - this.ruleNodeComponent.ruleNodeConfigComponent.definedConfigComponent.testScript$) { - this.ruleNodeComponent.ruleNodeConfigComponent.definedConfigComponent.testScript$(debugEventBody) - .subscribe((value) => { - if (value) { - this.selectedRuleNodeTabIndex = 0; - } - }) - } + const ruleNodeConfigComponent = this.ruleNodeComponent.ruleNodeConfigComponent; + const ruleNodeConfigDefinedComponent = ruleNodeConfigComponent.definedConfigComponent; + if (ruleNodeConfigComponent.useDefinedDirective() && ruleNodeConfigDefinedComponent.hasScript && ruleNodeConfigDefinedComponent.testScript) { + ruleNodeConfigDefinedComponent.testScript(debugEventBody); + } } onRuleNodeInit() { - if (this.ruleNodeComponent.ruleNodeConfigComponent.useDefinedDirective() && - this.ruleNodeComponent.ruleNodeConfigComponent.definedConfigComponent.getSupportTestFunction()) { - this.ruleNodeTestButtonLabel = this.ruleNodeComponent.ruleNodeConfigComponent.definedConfigComponent.getTestButtonLabel(); - } else { - this.ruleNodeTestButtonLabel = ''; - } + const ruleNodeConfigDefinedComponent = this.ruleNodeComponent.ruleNodeConfigComponent.definedConfigComponent; + if (this.ruleNodeComponent.ruleNodeConfigComponent.useDefinedDirective() && ruleNodeConfigDefinedComponent.hasScript) { + this.ruleNodeTestButtonLabel = ruleNodeConfigDefinedComponent.testScriptLabel; + } else { + this.ruleNodeTestButtonLabel = ''; + } + } + + switchToFirstTab() { + this.selectedRuleNodeTabIndex = 0; } saveRuleNode() { diff --git a/ui-ngx/src/app/shared/models/rule-node.models.ts b/ui-ngx/src/app/shared/models/rule-node.models.ts index dd427aaf09..2a7dedabec 100644 --- a/ui-ngx/src/app/shared/models/rule-node.models.ts +++ b/ui-ngx/src/app/shared/models/rule-node.models.ts @@ -73,13 +73,14 @@ export interface RuleNodeConfigurationDescriptor { export interface IRuleNodeConfigurationComponent { ruleNodeId: string; ruleChainId: string; + hasScript: boolean; + testScriptLabel?: string; + changeScript?: EventEmitter; ruleChainType: RuleChainType; configuration: RuleNodeConfiguration; configurationChanged: Observable; validate(); - getSupportTestFunction(): boolean; - getTestButtonLabel? (): string; - testScript$? (debugEventBody?: DebugRuleNodeEventBody): Observable; + testScript? (debugEventBody?: DebugRuleNodeEventBody); [key: string]: any; } @@ -92,6 +93,8 @@ export abstract class RuleNodeConfigurationComponent extends PageComponent imple ruleChainId: string; + hasScript: boolean = false; + ruleChainType: RuleChainType; configurationValue: RuleNodeConfiguration; @@ -115,8 +118,7 @@ export abstract class RuleNodeConfigurationComponent extends PageComponent imple configurationChangedEmiter = new EventEmitter(); configurationChanged = this.configurationChangedEmiter.asObservable(); - protected constructor(@Inject(Store) protected store: Store, - @Inject(TranslateService) protected translate: TranslateService) { + protected constructor(@Inject(Store) protected store: Store) { super(store); } @@ -134,14 +136,6 @@ export abstract class RuleNodeConfigurationComponent extends PageComponent imple this.onValidate(); } - getSupportTestFunction(): boolean { - return false; - } - - getTestButtonLabel(): string { - return this.translate.instant('rulenode.test-script-function'); - } - protected setupConfiguration(configuration: RuleNodeConfiguration) { this.onConfigurationSet(this.prepareInputConfig(configuration)); this.updateValidators(false);