diff --git a/src/main/java/se/kumliens/concept2runkeeper/domain/concept2/Concept2CsvActivity.java b/src/main/java/se/kumliens/concept2runkeeper/domain/concept2/Concept2CsvActivity.java index 2cdbe51..92d1bc8 100644 --- a/src/main/java/se/kumliens/concept2runkeeper/domain/concept2/Concept2CsvActivity.java +++ b/src/main/java/se/kumliens/concept2runkeeper/domain/concept2/Concept2CsvActivity.java @@ -1,5 +1,6 @@ package se.kumliens.concept2runkeeper.domain.concept2; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import lombok.EqualsAndHashCode; @@ -11,11 +12,15 @@ import se.kumliens.concept2runkeeper.domain.ExternalActivity; import org.springframework.data.annotation.PersistenceConstructor; +import se.kumliens.concept2runkeeper.domain.runkeeper.RunKeeperDistance; +import se.kumliens.concept2runkeeper.domain.runkeeper.RunKeeperHeartRate; + import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.Instant; import java.util.Date; +import java.util.List; /** * Created by svante2 on 2016-12-09. @@ -55,7 +60,7 @@ public class Concept2CsvActivity implements ExternalActivity { private String restTimeSeconds; @JsonProperty("Work Distance") - private String workDistance; + private Double workDistance; @JsonProperty("Rest Distance") private String restDistance; @@ -90,12 +95,15 @@ public class Concept2CsvActivity implements ExternalActivity { @JsonProperty("Comments") private String comments; + @JsonIgnore + private List strokeData; + public Concept2CsvActivity() { } @PersistenceConstructor - public Concept2CsvActivity(String date, String description, String formattedWorkTime, Double workTimeInSeconds, String formattedRestTime, String restTimeSeconds, String workDistance, String restDistance, String strokeRate, String avgWatts, + public Concept2CsvActivity(String date, String description, String formattedWorkTime, Double workTimeInSeconds, String formattedRestTime, String restTimeSeconds, Double workDistance, String restDistance, String strokeRate, String avgWatts, String avgHeartRate, String type, String pace, Double calPerHour, String age, String weight, String ranked, String comments) { this.date = date; this.description = description; diff --git a/src/main/java/se/kumliens/concept2runkeeper/runkeeper/RecordActivityRequest.java b/src/main/java/se/kumliens/concept2runkeeper/runkeeper/RecordActivityRequest.java index 822056e..2e8940e 100644 --- a/src/main/java/se/kumliens/concept2runkeeper/runkeeper/RecordActivityRequest.java +++ b/src/main/java/se/kumliens/concept2runkeeper/runkeeper/RecordActivityRequest.java @@ -37,7 +37,7 @@ public class RecordActivityRequest { //The total distance traveled, in meters @JsonProperty("total_distance") - private String distance; + private Double distance; @JsonProperty("total_calories") private Double totalCalories; @@ -68,7 +68,7 @@ public static RecordActivityRequest from(RunkeeperActivity runkeeperActivity, bo .type(runkeeperActivity.getType()) //.startTime(runkeeperActivity.getStartTime()) Not needed right now. .totalCalories(runkeeperActivity.getTotalCalories()) - .distance(runkeeperActivity.getDistance().toString()) + .distance(runkeeperActivity.getDistance()) .distances(runkeeperActivity.getDistances()) .duration(runkeeperActivity.getDuration()) .equipment(runkeeperActivity.getEquipment()) diff --git a/src/main/java/se/kumliens/concept2runkeeper/runkeeper/UpdateActivityRequest.java b/src/main/java/se/kumliens/concept2runkeeper/runkeeper/UpdateActivityRequest.java index 0c7805d..5534019 100644 --- a/src/main/java/se/kumliens/concept2runkeeper/runkeeper/UpdateActivityRequest.java +++ b/src/main/java/se/kumliens/concept2runkeeper/runkeeper/UpdateActivityRequest.java @@ -47,7 +47,7 @@ public class UpdateActivityRequest { @JsonProperty("notes") private String notes; - @JsonProperty("heart_rate") + @JsonProperty("heartRate") private List heartRates; public String getStartTime() { diff --git a/src/main/java/se/kumliens/concept2runkeeper/services/RunkeeperService.java b/src/main/java/se/kumliens/concept2runkeeper/services/RunkeeperService.java index 1c51683..2ab258b 100644 --- a/src/main/java/se/kumliens/concept2runkeeper/services/RunkeeperService.java +++ b/src/main/java/se/kumliens/concept2runkeeper/services/RunkeeperService.java @@ -6,7 +6,9 @@ import lombok.*; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.exception.ExceptionUtils; +import org.springframework.http.client.BufferingClientHttpRequestFactory; import org.springframework.http.client.ClientHttpResponse; +import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.web.client.DefaultResponseErrorHandler; import org.springframework.web.client.ResponseErrorHandler; import se.kumliens.concept2runkeeper.domain.runkeeper.ExternalRunkeeperData; @@ -25,6 +27,7 @@ import javax.annotation.PostConstruct; import java.io.IOException; +import java.io.InputStream; import java.net.URI; import java.text.ParseException; @@ -50,6 +53,13 @@ public class RunkeeperService { public void setup() { log.debug("Got some props: {}", props); restTemplate = new RestTemplate(); + + // set up a buffering request factory, so response body is always buffered + SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); + BufferingClientHttpRequestFactory bufferingClientHttpRequestFactory = new BufferingClientHttpRequestFactory(requestFactory); + requestFactory.setOutputStreaming(false); + restTemplate.setRequestFactory(bufferingClientHttpRequestFactory); + restTemplate.setErrorHandler(new DefaultResponseErrorHandler() { @Override public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException { @@ -58,6 +68,10 @@ public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOExceptio @Override public void handleError(ClientHttpResponse clientHttpResponse) throws IOException { + InputStream is = clientHttpResponse.getBody(); + java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A"); + String body = s.hasNext() ? s.next() : ""; + log.info("{}", body); int statusCode = clientHttpResponse.getStatusCode().value(); if(statusCode == 404) { throw new NoSuchActivityException(); @@ -154,6 +168,7 @@ public RunkeeperActivity updateActivity(RunkeeperActivity runkeeperActivity, Str throw new RuntimeException(e); } RequestEntity requestEntity = new RequestEntity(request, headers, PUT, URI.create(props.getBaseUrl().toString().concat(runkeeperActivity.getUri()))); + ResponseEntity response = restTemplate.exchange(requestEntity, RunkeeperActivity.class); log.info("got an updated activity: {}", response.getBody()); return response.getBody(); diff --git a/src/main/java/se/kumliens/concept2runkeeper/vaadin/MainUI.java b/src/main/java/se/kumliens/concept2runkeeper/vaadin/MainUI.java index afa45f0..5e19cf6 100644 --- a/src/main/java/se/kumliens/concept2runkeeper/vaadin/MainUI.java +++ b/src/main/java/se/kumliens/concept2runkeeper/vaadin/MainUI.java @@ -255,7 +255,7 @@ public static final String getNavigatorViewNameBasedOnView(Class } public User getUser() { - return (User) getSession().getAttribute(SESSION_ATTR_USER); + return getSession() != null ? (User) getSession().getAttribute(SESSION_ATTR_USER) : null; } diff --git a/src/main/java/se/kumliens/concept2runkeeper/vaadin/converters/Concept2DistanceConverter.java b/src/main/java/se/kumliens/concept2runkeeper/vaadin/converters/Concept2DistanceConverter.java index 3c7541c..64d6fec 100644 --- a/src/main/java/se/kumliens/concept2runkeeper/vaadin/converters/Concept2DistanceConverter.java +++ b/src/main/java/se/kumliens/concept2runkeeper/vaadin/converters/Concept2DistanceConverter.java @@ -12,28 +12,29 @@ * Created by svante2 on 2016-12-25. */ @Slf4j -public class Concept2DistanceConverter implements Converter { +public class Concept2DistanceConverter implements Converter { @Override - public String convertToModel(String value, Class targetType, Locale locale) throws ConversionException { - return value.replace("m","").replace(" ","").trim(); + public String convertToPresentation(Double value, Class targetType, Locale locale) throws ConversionException { + return value.toString(); } @Override - public String convertToPresentation(String value, Class targetType, Locale locale) throws ConversionException { - try { + public Double convertToModel(String value, Class targetType, Locale locale) throws ConversionException { + /*try { value = MoreObjects.firstNonNull(value, "0"); DecimalFormat decimalFormat = new DecimalFormat(Constants.DISTANCE_PATTERN); return decimalFormat.format(Double.valueOf(value.replace(" ","").trim())) + " m"; } catch (Exception e) { log.warn("Unable to parse {} to a number", value, e); return "n/a"; - } + }*/ + return Double.valueOf(value); } @Override - public Class getModelType() { - return String.class; + public Class getModelType() { + return Double.class; } @Override diff --git a/src/main/java/se/kumliens/concept2runkeeper/vaadin/views/sync/SynchronizeView.java b/src/main/java/se/kumliens/concept2runkeeper/vaadin/views/sync/SynchronizeView.java index ee7b97a..8dbc3a1 100644 --- a/src/main/java/se/kumliens/concept2runkeeper/vaadin/views/sync/SynchronizeView.java +++ b/src/main/java/se/kumliens/concept2runkeeper/vaadin/views/sync/SynchronizeView.java @@ -1,29 +1,5 @@ package se.kumliens.concept2runkeeper.vaadin.views.sync; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import se.kumliens.concept2runkeeper.domain.C2RActivity; -import se.kumliens.concept2runkeeper.domain.Synchronization; -import se.kumliens.concept2runkeeper.domain.concept2.Concept2CsvActivity; -import se.kumliens.concept2runkeeper.domain.concept2.Concept2CsvStrokeData; -import se.kumliens.concept2runkeeper.domain.runkeeper.ActivityType; -import se.kumliens.concept2runkeeper.domain.runkeeper.Equipment; -import se.kumliens.concept2runkeeper.domain.runkeeper.ExternalRunkeeperData; -import se.kumliens.concept2runkeeper.domain.runkeeper.InternalRunKeeperData; -import se.kumliens.concept2runkeeper.domain.runkeeper.RunKeeperHeartRate; -import se.kumliens.concept2runkeeper.domain.runkeeper.RunkeeperActivity; -import se.kumliens.concept2runkeeper.repos.C2RActivityRepo; -import se.kumliens.concept2runkeeper.runkeeper.RecordActivityRequest; -import se.kumliens.concept2runkeeper.services.NoSuchActivityException; -import se.kumliens.concept2runkeeper.services.RunkeeperService; -import se.kumliens.concept2runkeeper.vaadin.MainUI; -import se.kumliens.concept2runkeeper.vaadin.converters.Concept2DistanceConverter; -import se.kumliens.concept2runkeeper.vaadin.converters.Concept2WorkTimeConverter; -import se.kumliens.concept2runkeeper.vaadin.converters.RunKeeperDateConverter; -import se.kumliens.concept2runkeeper.vaadin.converters.RunKeeperDistanceConverter; -import se.kumliens.concept2runkeeper.vaadin.converters.RunKeeperDurationConverter; -import se.kumliens.concept2runkeeper.vaadin.events.ActivitySyncEvent; - import com.fasterxml.jackson.databind.MappingIterator; import com.fasterxml.jackson.dataformat.csv.CsvMapper; import com.fasterxml.jackson.dataformat.csv.CsvSchema; @@ -36,19 +12,12 @@ import com.vaadin.navigator.ViewChangeListener; import com.vaadin.server.Resource; import com.vaadin.spring.annotation.SpringView; -import com.vaadin.ui.Alignment; -import com.vaadin.ui.CheckBox; -import com.vaadin.ui.DragAndDropWrapper; -import com.vaadin.ui.Grid; -import com.vaadin.ui.Label; -import com.vaadin.ui.Panel; -import com.vaadin.ui.ProgressBar; -import com.vaadin.ui.TabSheet; -import com.vaadin.ui.Upload; -import com.vaadin.ui.VerticalSplitPanel; +import com.vaadin.ui.*; import com.vaadin.ui.renderers.ClickableRenderer.RendererClickListener; import com.vaadin.ui.renderers.ImageRenderer; import com.vaadin.ui.themes.ValoTheme; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.vaadin.dialogs.ConfirmDialog; @@ -63,12 +32,22 @@ import org.vaadin.viritin.layouts.MVerticalLayout; import org.vaadin.viritin.layouts.MWindow; import org.vaadin.viritin.ui.MNotification; +import se.kumliens.concept2runkeeper.domain.C2RActivity; +import se.kumliens.concept2runkeeper.domain.ExternalActivity; +import se.kumliens.concept2runkeeper.domain.Synchronization; +import se.kumliens.concept2runkeeper.domain.concept2.Concept2CsvActivity; +import se.kumliens.concept2runkeeper.domain.concept2.Concept2CsvStrokeData; +import se.kumliens.concept2runkeeper.domain.runkeeper.*; +import se.kumliens.concept2runkeeper.repos.C2RActivityRepo; +import se.kumliens.concept2runkeeper.runkeeper.RecordActivityRequest; +import se.kumliens.concept2runkeeper.services.NoSuchActivityException; +import se.kumliens.concept2runkeeper.services.RunkeeperService; +import se.kumliens.concept2runkeeper.vaadin.MainUI; +import se.kumliens.concept2runkeeper.vaadin.converters.*; +import se.kumliens.concept2runkeeper.vaadin.events.ActivitySyncEvent; + import javax.annotation.PostConstruct; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.IOException; +import java.io.*; import java.net.URI; import java.text.ParseException; import java.time.Instant; @@ -79,23 +58,12 @@ import java.util.concurrent.atomic.LongAdder; import static com.google.common.base.MoreObjects.firstNonNull; -import static com.vaadin.server.FontAwesome.CHAIN; -import static com.vaadin.server.FontAwesome.FILE_TEXT_O; -import static com.vaadin.server.FontAwesome.LONG_ARROW_RIGHT; -import static com.vaadin.server.FontAwesome.QUESTION_CIRCLE; +import static com.vaadin.server.FontAwesome.*; import static com.vaadin.server.Sizeable.Unit.EM; import static com.vaadin.shared.ui.label.ContentMode.HTML; import static com.vaadin.ui.Grid.SelectionMode.MULTI; import static com.vaadin.ui.Grid.SelectionMode.SINGLE; -import static com.vaadin.ui.themes.ValoTheme.BUTTON_BORDERLESS; -import static com.vaadin.ui.themes.ValoTheme.NOTIFICATION_CLOSABLE; -import static com.vaadin.ui.themes.ValoTheme.NOTIFICATION_ERROR; -import static com.vaadin.ui.themes.ValoTheme.NOTIFICATION_FAILURE; -import static com.vaadin.ui.themes.ValoTheme.NOTIFICATION_SMALL; -import static com.vaadin.ui.themes.ValoTheme.NOTIFICATION_SUCCESS; -import static com.vaadin.ui.themes.ValoTheme.NOTIFICATION_WARNING; -import static com.vaadin.ui.themes.ValoTheme.TABSHEET_FRAMED; -import static com.vaadin.ui.themes.ValoTheme.TABSHEET_PADDED_TABBAR; +import static com.vaadin.ui.themes.ValoTheme.*; import static java.util.stream.Collectors.joining; import static se.kumliens.concept2runkeeper.domain.Provider.CONCEPT2; import static se.kumliens.concept2runkeeper.domain.Provider.RUNKEEPER; @@ -207,7 +175,6 @@ public Class getType() { grid.addColumn(RunkeeperActivity.TYPE).setHeaderCaption("(RunKeeper-) Type").setExpandRatio(1); grid.addColumn(RunkeeperActivity.HEART_RATE).setRenderer(new SparklineRenderer()).setExpandRatio(2); - c2RActivityRepo.findByUserIdAndSource(ui.getUser().getEmail(), CONCEPT2).stream() .map(c2rActivity -> c2rActivity.getSynchronizations().stream().filter(synchronization -> synchronization.getTarget() == RUNKEEPER).findFirst()) .filter(Optional::isPresent) @@ -228,11 +195,12 @@ private RunkeeperActivity updateActivity(RunkeeperActivity runkeeperActivity) { return null; } - private static void addHeartRates(RunkeeperActivity runkeeperActivity, List strokeDatas) { - runkeeperActivity.getHeartRates().clear(); + private static void addHeartRates(Concept2CsvActivity concept2CsvActivity, List strokeData) { + concept2CsvActivity.setStrokeData(strokeData); + /*runkeeperActivity.getHeartRates().clear(); strokeDatas.forEach(strokeData -> { runkeeperActivity.getHeartRates().add(RunKeeperHeartRate.builder().heartRate((int) strokeData.getHeartRate()).timestamp(strokeData.getSeconds()).build()); - }); + });*/ } @@ -266,7 +234,7 @@ private Panel createFromContent() { "Here you can sync your Concept2 activities using the file export functionality from Concept2.
" + "
    " + "
  1. Export your activities as a .csv file from the Concept2 history tab
  2. " + - "
  3. Drop the file on the table below, select some activities and push the button.
  4. " + + "
  5. Drop the file on the table below, select some activities and push the green button.
  6. " + "
  7. Any activities not already synced with RunKeeper will be sent to RunKeeper.
  8. " + "
  9. Use the check-box to the right if you want to force sync of already synced activities.
") .withDelayMsec(15000).withStyleName(NOTIFICATION_SMALL).withStyleName(NOTIFICATION_CLOSABLE).withHtmlContentAllowed(true).display()); @@ -282,16 +250,47 @@ private Panel createFromContent() { csvTabLayout.add(new MHorizontalLayout(howToBtn, syncButton, forceSync).withAlign(forceSync, Alignment.MIDDLE_LEFT).withSpacing(true)); - MGrid grid = new MGrid<>(Concept2CsvActivity.class).withFullHeight().withFullWidth(); - grid.setSelectionMode(MULTI); - grid.setContainerDataSource(concept2Container); + GeneratedPropertyContainer generatedPropertyContainer = new GeneratedPropertyContainer(concept2Container); + + //Add a generated column for the heart rate + generatedPropertyContainer.addGeneratedProperty(RunkeeperActivity.HEART_RATE, new PropertyValueGenerator() { + @Override + public Number[] getValue(Item item, Object itemId, Object propertyId) { + return new Number[]{1, 2, 3, 2, 2, 4, 5, 4, 2, 1, 2, 5, 4, 5, 5, 2, 3, 2, 3, 4, 5}; + } + + @Override + public Class getType() { + return Number[].class; + } + }); + + //Add a generated column with the button to add stroke data + generatedPropertyContainer.addGeneratedProperty("addStrokeData", new PropertyValueGenerator() { + @Override + public Resource getValue(Item item, Object itemId, Object propertyId) { + return HEART_RATE; + } + + @Override + public Class getType() { + return Resource.class; + } + }); + + Grid grid = new Grid(generatedPropertyContainer); + grid.setSelectionMode(SINGLE); + grid.setWidth("100%"); + grid.setHeight("100%"); + grid.setContainerDataSource(generatedPropertyContainer); grid.removeAllColumns(); grid.addColumn("date").setHeaderCaption("Date"); grid.addColumn("workDistance").setHeaderCaption("Distance").setConverter(new Concept2DistanceConverter()); grid.addColumn("workTimeInSeconds").setHeaderCaption("Time").setConverter(new Concept2WorkTimeConverter()); grid.addColumn("pace").setHeaderCaption("Pace"); grid.addColumn("type").setHeaderCaption("(Concept2-) Type"); - grid.addColumn("addStrokeData").setRenderer(new ImageRenderer((RendererClickListener) e -> { + grid.addColumn(RunkeeperActivity.HEART_RATE).setRenderer(new SparklineRenderer()); + grid.addColumn("addStrokeData").setWidth(140).setRenderer(new ImageRenderer((RendererClickListener) e -> { Concept2CsvActivity concept2CsvActivity = (Concept2CsvActivity) e.getItemId(); Upload upload = null; try { @@ -316,30 +315,30 @@ private Panel createFromContent() { double lastDistance = CollectionUtils.isEmpty(strokeData) ? 0.0 : strokeData.get(strokeData.size() - 1).getDistance(); if (Math.abs(lastDistance - concept2CsvActivity.getWorkDistance()) > 2) { ConfirmDialog.show(getUI(), "Difference in distance", - "This result file has a different distance compared to the activity (the activity is " + concept2CsvActivity.getWorkDistance() + " meters but the result file is " + (int)lastDistance + " meters), are you sure you want to use this file?", + "This result file has a different distance compared to the activity (the activity is " + concept2CsvActivity.getWorkDistance() + " meters but the result file is " + (int) lastDistance + " meters), are you sure you want to use this file?", "Yes", "No", dialog -> { if (dialog.isConfirmed()) { - addHeartRates(concept2CsvActivity, strokeData); - //updateActivity(runkeeperActivity); - //TODO We don't update our internal representation here yet... + concept2CsvActivity.setStrokeData(strokeData); } }); } else { - addHeartRates(concept2CsvActivity, strokeData); - //updateActivity(runkeeperActivity); - //TODO We don't update our internal representation here yet... + concept2CsvActivity.setStrokeData(strokeData); } + ui.access(() -> { + grid.markAsDirtyRecursive(); + ui.push(); + }); } catch (Exception e1) { log.warn("Error reading file which should contain concept2 stroke data", e1); } }); - upload.setButtonCaption("Attach heart rate data"); + upload.setButtonCaption("Attach stroke data"); } catch (IOException e1) { log.warn("Error when adding stroke data to activity", e1); new MNotification("An error occurred: " + e1.getMessage()).withStyleName(NOTIFICATION_ERROR).display(); } - MWindow uploadwindow = new MWindow("Add heart rate data") + MWindow uploadwindow = new MWindow("Add stroke data") .withContent( new MPanel( new MHorizontalLayout(upload).withMargin(true).withSpacing(true).space())) @@ -360,14 +359,14 @@ private Panel createFromContent() { fromContent.expand(concept2TabSheet); - return new MPanel("Your Concept2 activities goes here").withContent(fromContent); + return new MPanel("Your Concept2 activities").withContent(fromContent); } //Handle the actual sync process to RunKeeper - private void setUpSyncClickHandler(MButton syncButton, MGrid concept2Grid) { + private void setUpSyncClickHandler(MButton syncButton, Grid concept2Grid) { syncButton.addClickListener(evt -> { - Collection selectedRows = concept2Grid.getSelectedRowsWithType(); + Collection selectedRows = concept2Grid.getSelectedRows(); if (selectedRows.isEmpty()) { log.warn("Sync button clicked without selected rows in the grid!"); new MNotification("No selection detected (this is a bug). Try to re-select the row(s)").withStyleName(NOTIFICATION_ERROR).withDelayMsec(5000).display(); @@ -379,7 +378,7 @@ private void setUpSyncClickHandler(MButton syncButton, MGrid { //new Thread(), really...? or Flowable from the rows. would also allow for nice cancel-button in mid-process @@ -390,19 +389,19 @@ private void setUpSyncClickHandler(MButton syncButton, MGrid { //If there is a stored activity then pick that one, otherwise create a new one. - C2RActivity c2RActivity = MoreObjects.firstNonNull(c2RActivityRepo.findBySourceId(csvActivity.getDate()), C2RActivity.builder() + C2RActivity c2RActivity = MoreObjects.firstNonNull(c2RActivityRepo.findBySourceId(((Concept2CsvActivity)csvActivity).getDate()), C2RActivity.builder() .userId(ui.getUser().getEmail()) .imported(Instant.now()) .source(CONCEPT2) - .sourceActivity(csvActivity) - .sourceId(csvActivity.getDate()) + .sourceActivity((ExternalActivity) csvActivity) + .sourceId(((Concept2CsvActivity)csvActivity).getDate()) .build()); //Add the sync if not already there if (forceSync.getValue() || c2RActivity.getSynchronizations().stream().filter(synchronization -> synchronization.getTarget() == RUNKEEPER).count() == 0) { try { log.info("No sync to RunKeeper found or force sync, let's do it"); - RecordActivityRequest request = createRecordActivityRequest(csvActivity, internalRunKeeperData, externalRunkeeperData); + RecordActivityRequest request = createRecordActivityRequest((Concept2CsvActivity) csvActivity, internalRunKeeperData, externalRunkeeperData); URI activityLocation = runkeeperService.recordActivity(request, ui.getUser().getInternalRunKeeperData().getToken()); newLocations.add(ui.getUser().getExternalRunkeeperData().getProfile().getProfile() + activityLocation.toString()); RunkeeperActivity rkActivity = runkeeperService.getActivity(ui.getUser().getInternalRunKeeperData().getToken(), activityLocation); @@ -476,7 +475,7 @@ private static RecordActivityRequest createRecordActivityRequest(Concept2CsvActi .heartRates(new ArrayList<>()).build(); } - private DragAndDropWrapper getDropAreaWithGrid(MGrid grid) { + private DragAndDropWrapper getDropAreaWithGrid(Grid grid) { final CsvFileDropHandler dropBox = new CsvFileDropHandler(grid, activities -> { if (!CollectionUtils.isEmpty(activities)) { grid.getContainerDataSource().removeAllItems();