Merge branch 'master' of github.com:thingsboard/thingsboard
This commit is contained in:
		
						commit
						1e41be45ba
					
				@ -21,6 +21,7 @@ import org.eclipse.californium.core.coap.MediaTypeRegistry;
 | 
			
		||||
import org.eclipse.californium.core.coap.Request;
 | 
			
		||||
import org.eclipse.californium.core.coap.Response;
 | 
			
		||||
import org.eclipse.californium.core.server.resources.CoapExchange;
 | 
			
		||||
import org.thingsboard.server.common.data.id.DeviceId;
 | 
			
		||||
import org.thingsboard.server.common.transport.SessionMsgListener;
 | 
			
		||||
import org.thingsboard.server.gen.transport.TransportProtos;
 | 
			
		||||
import org.thingsboard.server.transport.coap.client.TbCoapClientState;
 | 
			
		||||
@ -52,6 +53,11 @@ public abstract class AbstractSyncSessionCallback implements SessionMsgListener
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onDeviceDeleted(DeviceId deviceId) {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onToDeviceRpcRequest(UUID sessionId, TransportProtos.ToDeviceRpcRequestMsg toDeviceRequest) {
 | 
			
		||||
        logUnsupportedCommandMessage(toDeviceRequest);
 | 
			
		||||
 | 
			
		||||
@ -603,6 +603,13 @@ public class DeviceApiController implements TbTransportService {
 | 
			
		||||
            responseWriter.setResult(new ResponseEntity<>(JsonConverter.toJson(msg).toString(), HttpStatus.OK));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public void onDeviceDeleted(DeviceId deviceId) {
 | 
			
		||||
            UUID sessionId = new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB());
 | 
			
		||||
            log.trace("[{}] Received device deleted notification for device with id: {}",sessionId, deviceId);
 | 
			
		||||
            responseWriter.setResult(new ResponseEntity<>("Device was deleted!", HttpStatus.FORBIDDEN));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static MediaType parseMediaType(String contentType) {
 | 
			
		||||
 | 
			
		||||
@ -71,7 +71,7 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
 | 
			
		||||
 | 
			
		||||
    private LeshanServer server;
 | 
			
		||||
 | 
			
		||||
    @AfterStartUp
 | 
			
		||||
    @AfterStartUp(order = Integer.MAX_VALUE - 1)
 | 
			
		||||
    public void init() {
 | 
			
		||||
        this.server = getLhServer();
 | 
			
		||||
        /*
 | 
			
		||||
@ -83,8 +83,8 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
 | 
			
		||||
         */
 | 
			
		||||
        LwM2mTransportCoapResource otaCoapResource = new LwM2mTransportCoapResource(otaPackageDataCache, FIRMWARE_UPDATE_COAP_RESOURCE);
 | 
			
		||||
        this.server.coap().getServer().add(otaCoapResource);
 | 
			
		||||
        this.startLhServer();
 | 
			
		||||
        this.context.setServer(server);
 | 
			
		||||
        this.startLhServer();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void startLhServer() {
 | 
			
		||||
 | 
			
		||||
@ -20,6 +20,7 @@ import lombok.Getter;
 | 
			
		||||
import lombok.Setter;
 | 
			
		||||
import lombok.ToString;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.eclipse.leshan.core.link.LinkParamValue;
 | 
			
		||||
import org.eclipse.leshan.core.model.ObjectModel;
 | 
			
		||||
import org.eclipse.leshan.core.model.ResourceModel;
 | 
			
		||||
import org.eclipse.leshan.core.node.LwM2mMultipleResource;
 | 
			
		||||
@ -108,7 +109,7 @@ public class LwM2mClient implements Serializable {
 | 
			
		||||
    @Getter
 | 
			
		||||
    private Long edrxCycle;
 | 
			
		||||
    @Getter
 | 
			
		||||
    private Registration registration;
 | 
			
		||||
    private transient Registration registration;
 | 
			
		||||
    @Getter
 | 
			
		||||
    @Setter
 | 
			
		||||
    private boolean asleep;
 | 
			
		||||
@ -121,9 +122,9 @@ public class LwM2mClient implements Serializable {
 | 
			
		||||
    private boolean firstEdrxDownlink = true;
 | 
			
		||||
 | 
			
		||||
    @Getter
 | 
			
		||||
    private Set<ContentFormat> clientSupportContentFormats;
 | 
			
		||||
    private transient Set<ContentFormat> clientSupportContentFormats;
 | 
			
		||||
    @Getter
 | 
			
		||||
    private ContentFormat defaultContentFormat;
 | 
			
		||||
    private transient ContentFormat defaultContentFormat;
 | 
			
		||||
    @Getter
 | 
			
		||||
    private final AtomicInteger retryAttempts;
 | 
			
		||||
 | 
			
		||||
@ -430,9 +431,9 @@ public class LwM2mClient implements Serializable {
 | 
			
		||||
    static private Set<ContentFormat> clientSupportContentFormat(Registration registration) {
 | 
			
		||||
        Set<ContentFormat> contentFormats = new HashSet<>();
 | 
			
		||||
        contentFormats.add(ContentFormat.DEFAULT);
 | 
			
		||||
        String code = Arrays.stream(registration.getObjectLinks()).filter(link -> link.getUriReference().equals("/")).findFirst().get().getLinkParams().get("ct").getUnquoted();
 | 
			
		||||
        if (code != null) {
 | 
			
		||||
            Set<ContentFormat> codes = Stream.of(code.replaceAll("\"", "").split(" ", -1))
 | 
			
		||||
        LinkParamValue ct = Arrays.stream(registration.getObjectLinks()).filter(link -> link.getUriReference().equals("/")).findFirst().get().getLinkParams().get("ct");
 | 
			
		||||
        if (ct != null) {
 | 
			
		||||
            Set<ContentFormat> codes = Stream.of(ct.getUnquoted().replaceAll("\"", "").split(" ", -1))
 | 
			
		||||
                    .map(String::trim)
 | 
			
		||||
                    .map(Integer::parseInt)
 | 
			
		||||
                    .map(ContentFormat::fromCode)
 | 
			
		||||
 | 
			
		||||
@ -20,6 +20,7 @@ import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.eclipse.leshan.core.SecurityMode;
 | 
			
		||||
import org.eclipse.leshan.core.node.LwM2mPath;
 | 
			
		||||
import org.eclipse.leshan.server.registration.Registration;
 | 
			
		||||
import org.eclipse.leshan.server.registration.RegistrationStore;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.context.annotation.Lazy;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
@ -72,6 +73,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
 | 
			
		||||
    private final LwM2MSessionManager sessionManager;
 | 
			
		||||
    private final TransportDeviceProfileCache deviceProfileCache;
 | 
			
		||||
    private final LwM2MModelConfigService modelConfigService;
 | 
			
		||||
    private final RegistrationStore registrationStore;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    @Lazy
 | 
			
		||||
@ -118,8 +120,11 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
 | 
			
		||||
 | 
			
		||||
    private void updateFetchedClient(String nodeId, LwM2mClient client) {
 | 
			
		||||
        boolean updated = false;
 | 
			
		||||
        if (client.getRegistration() != null) {
 | 
			
		||||
            lwM2mClientsByRegistrationId.put(client.getRegistration().getId(), client);
 | 
			
		||||
        Registration registration = registrationStore.getRegistrationByEndpoint(client.getEndpoint());
 | 
			
		||||
 | 
			
		||||
        if (registration != null) {
 | 
			
		||||
            client.setRegistration(registration);
 | 
			
		||||
            lwM2mClientsByRegistrationId.put(registration.getId(), client);
 | 
			
		||||
        }
 | 
			
		||||
        if (client.getSession() != null) {
 | 
			
		||||
            client.refreshSessionId(nodeId);
 | 
			
		||||
 | 
			
		||||
@ -111,7 +111,11 @@ public abstract class RpcDownlinkRequestCallbackProxy<R, T> implements DownlinkR
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected void sendRpcReplyOnError(Exception e) {
 | 
			
		||||
        reply(LwM2MRpcResponseBody.builder().result(ResponseCode.INTERNAL_SERVER_ERROR.getName()).error(e.getMessage()).build());
 | 
			
		||||
        String error = e.getMessage();
 | 
			
		||||
        if (error == null) {
 | 
			
		||||
            error = e.toString();
 | 
			
		||||
        }
 | 
			
		||||
        reply(LwM2MRpcResponseBody.builder().result(ResponseCode.INTERNAL_SERVER_ERROR.getName()).error(error).build());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -48,6 +48,7 @@ import org.thingsboard.server.common.data.DeviceProfile;
 | 
			
		||||
import org.thingsboard.server.common.data.DeviceTransportType;
 | 
			
		||||
import org.thingsboard.server.common.data.TransportPayloadType;
 | 
			
		||||
import org.thingsboard.server.common.data.device.profile.MqttTopics;
 | 
			
		||||
import org.thingsboard.server.common.data.id.DeviceId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.OtaPackageId;
 | 
			
		||||
import org.thingsboard.server.common.data.ota.OtaPackageType;
 | 
			
		||||
import org.thingsboard.server.common.data.rpc.RpcStatus;
 | 
			
		||||
@ -1066,4 +1067,11 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
 | 
			
		||||
        deviceSessionCtx.onDeviceUpdate(sessionInfo, device, deviceProfileOpt);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onDeviceDeleted(DeviceId deviceId) {
 | 
			
		||||
        context.onAuthFailure(address);
 | 
			
		||||
        ChannelHandlerContext ctx = deviceSessionCtx.getChannel();
 | 
			
		||||
        ctx.close();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -19,6 +19,7 @@ import io.netty.channel.ChannelFuture;
 | 
			
		||||
import io.netty.handler.codec.mqtt.MqttMessage;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.thingsboard.server.common.data.DeviceProfile;
 | 
			
		||||
import org.thingsboard.server.common.data.id.DeviceId;
 | 
			
		||||
import org.thingsboard.server.common.data.rpc.RpcStatus;
 | 
			
		||||
import org.thingsboard.server.common.transport.SessionMsgListener;
 | 
			
		||||
import org.thingsboard.server.common.transport.TransportService;
 | 
			
		||||
@ -136,6 +137,11 @@ public class GatewayDeviceSessionCtx extends MqttDeviceAwareSessionContext imple
 | 
			
		||||
        // This feature is not supported in the TB IoT Gateway yet.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onDeviceDeleted(DeviceId deviceId) {
 | 
			
		||||
        parent.onDeviceDeleted(this.getSessionInfo().getDeviceName());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private boolean isAckExpected(MqttMessage message) {
 | 
			
		||||
        return message.fixedHeader().qosLevel().value() > 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -178,6 +178,10 @@ public class GatewaySessionHandler {
 | 
			
		||||
        devices.forEach(this::deregisterSession);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void onDeviceDeleted(String deviceName) {
 | 
			
		||||
        deregisterSession(deviceName);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String getNodeId() {
 | 
			
		||||
        return context.getNodeId();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -45,6 +45,8 @@ public interface SessionMsgListener {
 | 
			
		||||
 | 
			
		||||
    void onToServerRpcResponse(ToServerRpcResponseMsg toServerResponse);
 | 
			
		||||
 | 
			
		||||
    void onDeviceDeleted(DeviceId deviceId);
 | 
			
		||||
 | 
			
		||||
    default void onUplinkNotification(UplinkNotificationMsg notificationMsg){};
 | 
			
		||||
 | 
			
		||||
    default void onToTransportUpdateCredentials(ToTransportUpdateCredentialsProto toTransportUpdateCredentials){}
 | 
			
		||||
@ -54,8 +56,6 @@ public interface SessionMsgListener {
 | 
			
		||||
    default void onDeviceUpdate(TransportProtos.SessionInfoProto sessionInfo, Device device,
 | 
			
		||||
                                Optional<DeviceProfile> deviceProfileOpt) {}
 | 
			
		||||
 | 
			
		||||
    default void onDeviceDeleted(DeviceId deviceId) {}
 | 
			
		||||
 | 
			
		||||
    default void onResourceUpdate(TransportProtos.ResourceUpdateMsg resourceUpdateMsgOpt) {}
 | 
			
		||||
 | 
			
		||||
    default void onResourceDelete(TransportProtos.ResourceDeleteMsg resourceUpdateMsgOpt) {}
 | 
			
		||||
 | 
			
		||||
@ -91,6 +91,7 @@ import org.thingsboard.server.queue.provider.TbQueueProducerProvider;
 | 
			
		||||
import org.thingsboard.server.queue.provider.TbTransportQueueFactory;
 | 
			
		||||
import org.thingsboard.server.queue.scheduler.SchedulerComponent;
 | 
			
		||||
import org.thingsboard.server.queue.usagestats.TbApiUsageClient;
 | 
			
		||||
import org.thingsboard.server.queue.util.AfterStartUp;
 | 
			
		||||
import org.thingsboard.server.queue.util.TbTransportComponent;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.PostConstruct;
 | 
			
		||||
@ -227,6 +228,10 @@ public class DefaultTransportService implements TransportService {
 | 
			
		||||
        transportNotificationsConsumer.subscribe(Collections.singleton(tpi));
 | 
			
		||||
        transportApiRequestTemplate.init();
 | 
			
		||||
        mainConsumerExecutor = Executors.newSingleThreadExecutor(ThingsBoardThreadFactory.forName("transport-consumer"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @AfterStartUp
 | 
			
		||||
    private void start() {
 | 
			
		||||
        mainConsumerExecutor.execute(() -> {
 | 
			
		||||
            while (!stopped) {
 | 
			
		||||
                try {
 | 
			
		||||
 | 
			
		||||
@ -339,6 +339,21 @@ public class MqttClientTest extends AbstractContainerTest {
 | 
			
		||||
        restClient.getRestTemplate().delete(HTTPS_URL + "/api/device/" + device.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void deviceDeletedClosingSession() throws Exception {
 | 
			
		||||
        restClient.login("tenant@thingsboard.org", "tenant");
 | 
			
		||||
        String deviceForDeletingTestName = "Device for deleting notification test";
 | 
			
		||||
        Device device = createDevice(deviceForDeletingTestName);
 | 
			
		||||
        DeviceCredentials deviceCredentials = restClient.getDeviceCredentialsByDeviceId(device.getId()).get();
 | 
			
		||||
 | 
			
		||||
        MqttMessageListener listener = new MqttMessageListener();
 | 
			
		||||
        MqttClient mqttClient = getMqttClient(deviceCredentials, listener);
 | 
			
		||||
 | 
			
		||||
        restClient.deleteDevice(device.getId());
 | 
			
		||||
        TimeUnit.SECONDS.sleep(3);
 | 
			
		||||
        Assert.assertFalse(mqttClient.isConnected());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private RuleChainId createRootRuleChainForRpcResponse() throws Exception {
 | 
			
		||||
        RuleChain newRuleChain = new RuleChain();
 | 
			
		||||
        newRuleChain.setName("testRuleChain");
 | 
			
		||||
 | 
			
		||||
@ -374,7 +374,15 @@ public class MqttGatewayClientTest extends AbstractContainerTest {
 | 
			
		||||
        Assert.assertEquals(clientResponse.toString(), serverResponse.getBody());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        private void checkAttribute(boolean client, String expectedValue) throws Exception{
 | 
			
		||||
    @Test
 | 
			
		||||
    public void deviceCreationAfterDeleted() throws Exception {
 | 
			
		||||
        restClient.getRestTemplate().delete(HTTPS_URL + "/api/device/" + this.createdDevice.getId());
 | 
			
		||||
        Optional<Device> deletedDevice = restClient.getDeviceById(this.createdDevice.getId());
 | 
			
		||||
        Assert.assertTrue(deletedDevice.isEmpty());
 | 
			
		||||
        this.createdDevice = createDeviceThroughGateway(mqttClient, gatewayDevice);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void checkAttribute(boolean client, String expectedValue) throws Exception {
 | 
			
		||||
        JsonObject gatewayAttributesRequest = new JsonObject();
 | 
			
		||||
        int messageId = new Random().nextInt(100);
 | 
			
		||||
        gatewayAttributesRequest.addProperty("id", messageId);
 | 
			
		||||
 | 
			
		||||
@ -134,6 +134,7 @@ import {
 | 
			
		||||
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
 | 
			
		||||
import cssjs from '@core/css/css';
 | 
			
		||||
import { DOCUMENT } from '@angular/common';
 | 
			
		||||
import { IAliasController } from '@core/api/widget-api.models';
 | 
			
		||||
 | 
			
		||||
// @dynamic
 | 
			
		||||
@Component({
 | 
			
		||||
@ -179,6 +180,9 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
 | 
			
		||||
  @Input()
 | 
			
		||||
  parentDashboard?: IDashboardComponent = null;
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  parentAliasController?: IAliasController = null;
 | 
			
		||||
 | 
			
		||||
  @ViewChild('dashboardContainer') dashboardContainer: ElementRef<HTMLElement>;
 | 
			
		||||
 | 
			
		||||
  prevDashboard: Dashboard;
 | 
			
		||||
@ -419,7 +423,7 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
 | 
			
		||||
    this.readonly = this.embedded || (this.singlePageMode && !this.widgetEditMode && !this.route.snapshot.queryParamMap.get('edit'))
 | 
			
		||||
                    || this.forceFullscreen || this.isMobileApp || this.authUser.authority === Authority.CUSTOMER_USER;
 | 
			
		||||
 | 
			
		||||
    this.dashboardCtx.aliasController = new AliasController(this.utils,
 | 
			
		||||
    this.dashboardCtx.aliasController = this.parentAliasController ? this.parentAliasController : new AliasController(this.utils,
 | 
			
		||||
      this.entityService,
 | 
			
		||||
      this.translate,
 | 
			
		||||
      () => this.dashboardCtx.stateController,
 | 
			
		||||
 | 
			
		||||
@ -21,7 +21,8 @@
 | 
			
		||||
  [hideToolbar]="true"
 | 
			
		||||
  [currentState]="currentState"
 | 
			
		||||
  [dashboard]="dashboard"
 | 
			
		||||
  [parentDashboard]="parentDashboard">
 | 
			
		||||
  [parentDashboard]="parentDashboard"
 | 
			
		||||
  [parentAliasController]="parentAliasController">
 | 
			
		||||
</tb-dashboard-page>
 | 
			
		||||
<div class="tb-absolute-fill tb-widget-error" *ngIf="!stateExists">
 | 
			
		||||
  <span>{{ 'dashboard.non-existent-dashboard-state-error' | translate:{stateId} }}</span>
 | 
			
		||||
 | 
			
		||||
@ -19,7 +19,7 @@ import { PageComponent } from '@shared/components/page.component';
 | 
			
		||||
import { Store } from '@ngrx/store';
 | 
			
		||||
import { AppState } from '@core/core.state';
 | 
			
		||||
import { Dashboard, DashboardLayoutId } from '@shared/models/dashboard.models';
 | 
			
		||||
import { StateObject } from '@core/api/widget-api.models';
 | 
			
		||||
import { IAliasController, StateObject } from '@core/api/widget-api.models';
 | 
			
		||||
import { updateEntityParams, WidgetContext } from '@home/models/widget-component.models';
 | 
			
		||||
import { deepClone, isDefinedAndNotNull, isNotEmptyStr, objToBase64 } from '@core/utils';
 | 
			
		||||
import { IDashboardComponent } from '@home/models/dashboard-component.models';
 | 
			
		||||
@ -63,6 +63,8 @@ export class DashboardStateComponent extends PageComponent implements OnInit, On
 | 
			
		||||
 | 
			
		||||
  parentDashboard: IDashboardComponent;
 | 
			
		||||
 | 
			
		||||
  parentAliasController: IAliasController;
 | 
			
		||||
 | 
			
		||||
  stateExists = true;
 | 
			
		||||
 | 
			
		||||
  private stateSubscription: Subscription;
 | 
			
		||||
@ -92,6 +94,7 @@ export class DashboardStateComponent extends PageComponent implements OnInit, On
 | 
			
		||||
      this.parentDashboard = this.ctx.parentDashboard ?
 | 
			
		||||
        this.ctx.parentDashboard : this.ctx.dashboard;
 | 
			
		||||
      if (this.syncParentStateParams) {
 | 
			
		||||
        this.parentAliasController = this.parentDashboard.aliasController;
 | 
			
		||||
        this.stateSubscription = this.ctx.stateController.dashboardCtrl.dashboardCtx.stateChanged.subscribe(() => {
 | 
			
		||||
          this.updateCurrentState();
 | 
			
		||||
          this.cd.markForCheck();
 | 
			
		||||
 | 
			
		||||
@ -41,6 +41,22 @@ export function createTooltip(target: L.Layer,
 | 
			
		||||
    return popup;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function disablePopup(target: L.Layer) {
 | 
			
		||||
  if (target.isPopupOpen()) {
 | 
			
		||||
    target.closePopup();
 | 
			
		||||
  }
 | 
			
		||||
  target.unbindPopup();
 | 
			
		||||
  target.off('popupopen');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function enablePopup(target: L.Layer, popup: L.Popup,
 | 
			
		||||
                            settings: MarkerSettings | PolylineSettings | PolygonSettings, datasource: Datasource) {
 | 
			
		||||
  target.bindPopup(popup);
 | 
			
		||||
  target.on('popupopen', () => {
 | 
			
		||||
    bindPopupActions(popup, settings, datasource);
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function bindPopupActions(popup: L.Popup, settings: MarkerSettings | PolylineSettings | PolygonSettings,
 | 
			
		||||
                                 datasource: Datasource) {
 | 
			
		||||
  const actions = popup.getElement().getElementsByClassName('tb-custom-action');
 | 
			
		||||
 | 
			
		||||
@ -23,7 +23,7 @@ import {
 | 
			
		||||
  MarkerSettings,
 | 
			
		||||
  UnitedMapSettings
 | 
			
		||||
} from './map-models';
 | 
			
		||||
import { bindPopupActions, createTooltip, } from './maps-utils';
 | 
			
		||||
import { bindPopupActions, createTooltip, disablePopup, enablePopup, } from './maps-utils';
 | 
			
		||||
import { aspectCache, fillPattern, parseWithTranslation, processPattern, safeExecute } from './common-maps-utils';
 | 
			
		||||
import tinycolor from 'tinycolor2';
 | 
			
		||||
import { isDefined, isDefinedAndNotNull } from '@core/utils';
 | 
			
		||||
@ -37,6 +37,7 @@ export class Marker {
 | 
			
		||||
    tooltip: L.Popup;
 | 
			
		||||
    data: FormattedData;
 | 
			
		||||
    dataSources: FormattedData[];
 | 
			
		||||
    isDragging = false;
 | 
			
		||||
 | 
			
		||||
  constructor(private map: LeafletMap, private location: L.LatLng, public settings: UnitedMapSettings,
 | 
			
		||||
              data?: FormattedData, dataSources?, onDragendListener?) {
 | 
			
		||||
@ -64,17 +65,31 @@ export class Marker {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.settings.markerClick) {
 | 
			
		||||
            this.leafletMarker.on('click', (event: LeafletMouseEvent) => {
 | 
			
		||||
                for (const action in this.settings.markerClick) {
 | 
			
		||||
            if (!this.isDragging) {
 | 
			
		||||
                this.leafletMarker.on('click', (event: LeafletMouseEvent) => {
 | 
			
		||||
                  for (const action in this.settings.markerClick) {
 | 
			
		||||
                    if (typeof (this.settings.markerClick[action]) === 'function') {
 | 
			
		||||
                        this.settings.markerClick[action](event.originalEvent, this.data.$datasource);
 | 
			
		||||
                      this.settings.markerClick[action](event.originalEvent, this.data.$datasource);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
                  }
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (settings.draggableMarker && onDragendListener) {
 | 
			
		||||
          this.leafletMarker.on('pm:dragend', (e) => onDragendListener(e, this.data));
 | 
			
		||||
          this.leafletMarker.on('pm:dragend', (e) => {
 | 
			
		||||
            onDragendListener(e, this.data);
 | 
			
		||||
            this.isDragging = false;
 | 
			
		||||
            if (settings.showTooltip && settings.showTooltipAction === 'click') {
 | 
			
		||||
              enablePopup(this.leafletMarker, this.tooltip, settings, this.data.$datasource);
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
          this.leafletMarker.on('pm:dragstart', (e) => {
 | 
			
		||||
            this.isDragging = true;
 | 
			
		||||
            if (settings.showTooltip && settings.showTooltipAction === 'click') {
 | 
			
		||||
              disablePopup(this.leafletMarker);
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user