Skip to content

Commit 906df19

Browse files
Merge branch 'dev' into dynamic-style-fixes
2 parents 7929e20 + a28726f commit 906df19

File tree

18 files changed

+139
-31
lines changed

18 files changed

+139
-31
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ And we mean it... Day by day!
9090
## 💻 Deployment Options
9191
[![Deploy to AWS using Stitch](https://img.shields.io/badge/deploy_with-Stitch-%23E369F7?logo=amazonaws&color=%23E369F7)](https://deploy.stitch.tech/lowcoder/lowcoder)
9292

93-
[![Deploy in minutes on Elest.io](https://raw.githubusercontent.com/elestio-examples/element/main/deploy-on-elestio.png)](https://elest.io/open-source/lowcoder)
93+
[![Deploy to Elestio](https://img.shields.io/badge/Deploy_to-Elestio-%23E369F7?color=orange)](https://elest.io/open-source/lowcoder)
9494

9595
You can access Lowcoder from [cloud-hosted version](https://app.lowcoder.cloud/) at any time, or use the following resources for self-host Lowcoder on different platforms:
9696
- [Docker](https://docs.lowcoder.cloud/lowcoder-documentation/setup-and-run/self-hosting)
@@ -110,4 +110,4 @@ Like ... [@Darkjamin](https://github.com/Darkjamin), [@spacegoats-io](https://g
110110

111111
## Intro Video
112112

113-
[![Watch the video](https://i.ytimg.com/vi/s4ltAqS0hzM/maxresdefault.jpg?sqp=-oaymwEmCIAKENAF8quKqQMa8AEB-AH-CYAC0AWKAgwIABABGD0gSShyMA8=&rs=AOn4CLAlPOIFdtauythoBKNPXhi6XGwlDQ)](https://youtu.be/s4ltAqS0hzM?feature=shared)
113+
[![Watch the video](https://i.ytimg.com/vi/s4ltAqS0hzM/maxresdefault.jpg?sqp=-oaymwEmCIAKENAF8quKqQMa8AEB-AH-CYAC0AWKAgwIABABGD0gSShyMA8=&rs=AOn4CLAlPOIFdtauythoBKNPXhi6XGwlDQ)](https://youtu.be/s4ltAqS0hzM?feature=shared)

client/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080
"chalk": "4",
8181
"flag-icons": "^7.2.1",
8282
"number-precision": "^1.6.0",
83-
"posthog-js": "^1.144.2",
83+
"posthog-js": "^1.155.4",
8484
"react-countup": "^6.5.3",
8585
"react-player": "^2.11.0",
8686
"resize-observer-polyfill": "^1.5.1",

client/packages/lowcoder/src/comps/generators/list.tsx

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ export type CustomListAction<CompCtor extends CompConstructor = CompConstructor>
2626
>;
2727

2828
type ListAction<CompCtor extends CompConstructor = CompConstructor> =
29+
| {
30+
type: "setChildrens";
31+
value: Array<ConstructorToDataType<CompCtor>>;
32+
}
2933
| {
3034
type: "push";
3135
value: ConstructorToDataType<CompCtor>;
@@ -145,7 +149,19 @@ export function list<ChildCompCtor extends CompConstructor<any, any>>(
145149

146150
private reduceCustom(action: ListAction<ChildCompCtor>): this {
147151
switch (action.type) {
148-
case "push":
152+
case "setChildrens": {
153+
const childrenMap: Record<number, ConstructorToComp<ChildCompCtor>> = {};
154+
const childrenOrder: number[] = [];
155+
action.value.forEach((children: any, key: number) => {
156+
childrenMap[key] = newChild(this.dispatch, String(key), children);
157+
childrenOrder.push(key);
158+
})
159+
return setFieldsNoTypeCheck(this, {
160+
children: childrenMap,
161+
childrenOrder: childrenOrder,
162+
});
163+
}
164+
case "push": {
149165
const key = this.genKey();
150166
const newChildren = {
151167
...this.children,
@@ -155,6 +171,7 @@ export function list<ChildCompCtor extends CompConstructor<any, any>>(
155171
children: newChildren,
156172
childrenOrder: [...this.childrenOrder, key],
157173
});
174+
}
158175
case "pushComp": {
159176
const key = this.genKey();
160177
const newChildren = {
@@ -209,6 +226,17 @@ export function list<ChildCompCtor extends CompConstructor<any, any>>(
209226
}
210227
}
211228
}
229+
230+
setChildrensAction(value: Array<ConstructorToDataType<ChildCompCtor>>) {
231+
return customAction<ListAction<ChildCompCtor>>(
232+
{
233+
type: "setChildrens",
234+
value: value,
235+
},
236+
true
237+
);
238+
}
239+
212240
pushAction(value: ConstructorToDataType<ChildCompCtor>) {
213241
return customAction<ListAction<ChildCompCtor>>(
214242
{

client/yarn.lock

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13822,7 +13822,7 @@ coolshapes-react@lowcoder-org/coolshapes-react:
1382213822
lowcoder-cli: "workspace:^"
1382313823
mq-polyfill: ^1.1.8
1382413824
number-precision: ^1.6.0
13825-
posthog-js: ^1.144.2
13825+
posthog-js: ^1.155.4
1382613826
prettier: ^3.1.0
1382713827
react-countup: ^6.5.3
1382813828
react-player: ^2.11.0
@@ -16126,14 +16126,14 @@ coolshapes-react@lowcoder-org/coolshapes-react:
1612616126
languageName: node
1612716127
linkType: hard
1612816128

16129-
"posthog-js@npm:^1.144.2":
16130-
version: 1.144.2
16131-
resolution: "posthog-js@npm:1.144.2"
16129+
"posthog-js@npm:^1.155.4":
16130+
version: 1.155.4
16131+
resolution: "posthog-js@npm:1.155.4"
1613216132
dependencies:
1613316133
fflate: ^0.4.8
1613416134
preact: ^10.19.3
1613516135
web-vitals: ^4.0.1
16136-
checksum: c856f49a34b825eb0678b40e137affa4a79a29ff64205f059a9a0ad78ce6ac8b3d8413f955e3fa72b08cf91e923e443aedb7e41b2e40c76c1cab20b88fe1c3d7
16136+
checksum: 749d180a4bfda0cb89307bad81eb230523c3e8f03dc94ac35dde212a130593a23dd98768bbff64753931dc501bca345397d7b39157dcc6eb174d57bd647c33d5
1613716137
languageName: node
1613816138
linkType: hard
1613916139

server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/model/Application.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ public class Application extends HasIdAndAuditing {
5252
private Boolean publicToMarketplace;
5353
@Setter
5454
private Boolean agencyProfile;
55+
@Getter
56+
@Setter
57+
private String editingUserId;
5558

5659
public Application(
5760
@JsonProperty("orgId") String organizationId,
@@ -63,7 +66,8 @@ public Application(
6366
@JsonProperty("editingApplicationDSL") Map<String, Object> editingApplicationDSL,
6467
@JsonProperty("publicToAll") Boolean publicToAll,
6568
@JsonProperty("publicToMarketplace") Boolean publicToMarketplace,
66-
@JsonProperty("agencyProfile") Boolean agencyProfile
69+
@JsonProperty("agencyProfile") Boolean agencyProfile,
70+
@JsonProperty("editingUserId") String editingUserId
6771
) {
6872
this.gid = gid;
6973
this.organizationId = organizationId;
@@ -75,6 +79,7 @@ public Application(
7579
this.publicToMarketplace = publicToMarketplace;
7680
this.agencyProfile = agencyProfile;
7781
this.editingApplicationDSL = editingApplicationDSL;
82+
this.editingUserId = editingUserId;
7883
}
7984

8085
@Transient

server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/service/ApplicationHistorySnapshotService.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ public interface ApplicationHistorySnapshotService {
1818

1919
Mono<ApplicationHistorySnapshot> getHistorySnapshotDetail(String historySnapshotId);
2020

21+
Mono<ApplicationHistorySnapshot> getLastSnapshotByApp(String applicationId);
2122
}

server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/service/ApplicationService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ public interface ApplicationService {
2323

2424
Mono<Application> publish(String applicationId);
2525

26+
Mono<Boolean> updateEditState(String applicationId, Boolean editingFinished);
27+
2628
Mono<Application> create(Application newApplication, String visitorId);
2729

2830
Flux<Application> findByOrganizationIdWithDsl(String organizationId);

server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/service/ApplicationServiceImpl.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,16 @@ public Mono<Application> publish(String applicationId) {
9393
});
9494
}
9595

96+
@Override
97+
public Mono<Boolean> updateEditState(String applicationId, Boolean editingFinished) {
98+
return findById(applicationId)
99+
.flatMap(newApplication -> {
100+
Application application = Application.builder().editingUserId("").build();
101+
if(editingFinished) return mongoUpsertHelper.updateById(application, applicationId);
102+
return Mono.just(true);
103+
});
104+
}
105+
96106
@Override
97107
public Mono<Application> create(Application newApplication, String visitorId) {
98108
return repository.save(newApplication)

server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/service/impl/ApplicationHistorySnapshotServiceImpl.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import static org.lowcoder.sdk.util.ExceptionUtils.deferredError;
55
import static org.lowcoder.sdk.util.ExceptionUtils.ofException;
66

7+
import java.time.Instant;
78
import java.util.List;
89
import java.util.Map;
910

@@ -57,4 +58,13 @@ public Mono<ApplicationHistorySnapshot> getHistorySnapshotDetail(String historyS
5758
return repository.findById(historySnapshotId)
5859
.switchIfEmpty(deferredError(INVALID_HISTORY_SNAPSHOT, "INVALID_HISTORY_SNAPSHOT", historySnapshotId));
5960
}
61+
62+
@Override
63+
public Mono<ApplicationHistorySnapshot> getLastSnapshotByApp(String applicationId) {
64+
ApplicationHistorySnapshot _default = new ApplicationHistorySnapshot();
65+
_default.setCreatedAt(Instant.ofEpochMilli(0));
66+
_default.setCreatedBy("");
67+
return repository.findAllByApplicationId(applicationId, PageRequest.of(0, 1).withSort(Direction.DESC, "createdAt"))
68+
.switchIfEmpty(Mono.just(_default)).next();
69+
}
6070
}

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/application/ApplicationApiService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ public interface ApplicationApiService {
3535

3636
Mono<ApplicationView> publish(String applicationId);
3737

38+
Mono<Boolean> updateEditState(String applicationId, ApplicationEndpoints.UpdateEditStateRequest updateEditStateRequest);
39+
3840
Mono<Boolean> grantPermission(String applicationId,
3941
Set<String> userIds,
4042
Set<String> groupIds, ResourceRole role);

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/application/ApplicationApiServiceImpl.java

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,8 @@
2121
import org.lowcoder.api.permission.PermissionHelper;
2222
import org.lowcoder.api.permission.view.PermissionItemView;
2323
import org.lowcoder.api.usermanagement.OrgDevChecker;
24-
import org.lowcoder.domain.application.model.Application;
25-
import org.lowcoder.domain.application.model.ApplicationRequestType;
26-
import org.lowcoder.domain.application.model.ApplicationStatus;
27-
import org.lowcoder.domain.application.model.ApplicationType;
24+
import org.lowcoder.domain.application.model.*;
25+
import org.lowcoder.domain.application.service.ApplicationHistorySnapshotService;
2826
import org.lowcoder.domain.application.service.ApplicationService;
2927
import org.lowcoder.domain.datasource.model.Datasource;
3028
import org.lowcoder.domain.datasource.service.DatasourceService;
@@ -45,7 +43,6 @@
4543
import org.lowcoder.sdk.exception.BizException;
4644
import org.lowcoder.sdk.plugin.common.QueryExecutor;
4745
import org.lowcoder.sdk.util.ExceptionUtils;
48-
import org.springframework.context.annotation.Lazy;
4946
import org.springframework.http.HttpHeaders;
5047
import org.springframework.stereotype.Service;
5148
import reactor.core.publisher.Flux;
@@ -58,7 +55,6 @@
5855
import java.util.List;
5956
import java.util.Map;
6057
import java.util.Set;
61-
import java.util.concurrent.TimeUnit;
6258
import java.util.stream.Collectors;
6359

6460
import static org.lowcoder.domain.application.model.ApplicationStatus.NORMAL;
@@ -94,6 +90,7 @@ public class ApplicationApiServiceImpl implements ApplicationApiService {
9490
private final TemplateService templateService;
9591
private final PermissionHelper permissionHelper;
9692
private final DatasourceService datasourceService;
93+
private final ApplicationHistorySnapshotService applicationHistorySnapshotService;
9794

9895
@Override
9996
public Mono<ApplicationView> create(CreateApplicationRequest createApplicationRequest) {
@@ -105,7 +102,7 @@ public Mono<ApplicationView> create(CreateApplicationRequest createApplicationRe
105102
NORMAL,
106103
createApplicationRequest.publishedApplicationDSL(),
107104
createApplicationRequest.editingApplicationDSL(),
108-
false, false, false);
105+
false, false, false, "");
109106

110107
if (StringUtils.isBlank(application.getOrganizationId())) {
111108
return deferredError(INVALID_PARAMETER, "ORG_ID_EMPTY");
@@ -259,19 +256,28 @@ public Mono<ApplicationView> getEditingApplication(String applicationId) {
259256
.delayUntil(application -> checkApplicationStatus(application, NORMAL)))
260257
.zipWhen(tuple -> applicationService.getAllDependentModulesFromApplication(tuple.getT2(), false), TupleUtils::merge)
261258
.zipWhen(tuple -> organizationService.getOrgCommonSettings(tuple.getT2().getOrganizationId()), TupleUtils::merge)
262-
.map(tuple -> {
263-
ResourcePermission permission = tuple.getT1();
264-
Application application = tuple.getT2();
265-
List<Application> dependentModules = tuple.getT3();
266-
Map<String, Object> commonSettings = tuple.getT4();
259+
.zipWhen(tuple -> sessionUserService.getVisitorId().zipWith(applicationHistorySnapshotService.getLastSnapshotByApp(applicationId)))
260+
.flatMap(tuple -> {
261+
ResourcePermission permission = tuple.getT1().getT1();
262+
Application application = tuple.getT1().getT2();
263+
List<Application> dependentModules = tuple.getT1().getT3();
264+
Map<String, Object> commonSettings = tuple.getT1().getT4();
265+
String visitorId = tuple.getT2().getT1();
266+
ApplicationHistorySnapshot lastSnapshot = tuple.getT2().getT2();
267+
268+
if(!visitorId.equals(application.getEditingUserId()) && lastSnapshot.getCreatedAt().compareTo(Instant.now().minusSeconds(300)) < 0) {
269+
application.setEditingUserId(visitorId);
270+
}
271+
267272
Map<String, Map<String, Object>> dependentModuleDsl = dependentModules.stream()
268273
.collect(Collectors.toMap(Application::getId, Application::getLiveApplicationDsl, (a, b) -> b));
269-
return ApplicationView.builder()
274+
return applicationService.updateById(applicationId, application).map(__ ->
275+
ApplicationView.builder()
270276
.applicationInfoView(buildView(application, permission.getResourceRole().getValue()))
271277
.applicationDSL(application.getEditingApplicationDSL())
272278
.moduleDSL(dependentModuleDsl)
273279
.orgCommonSettings(commonSettings)
274-
.build();
280+
.build());
275281
});
276282
}
277283

@@ -365,6 +371,15 @@ public Mono<ApplicationView> publish(String applicationId) {
365371
.build()));
366372
}
367373

374+
@Override
375+
public Mono<Boolean> updateEditState(String applicationId, ApplicationEndpoints.UpdateEditStateRequest updateEditStateRequest) {
376+
return checkApplicationStatus(applicationId, NORMAL)
377+
.then(sessionUserService.getVisitorId())
378+
.flatMap(userId -> resourcePermissionService.checkAndReturnMaxPermission(userId,
379+
applicationId, EDIT_APPLICATIONS))
380+
.flatMap(permission -> applicationService.updateEditState(applicationId, updateEditStateRequest.editingFinished()));
381+
}
382+
368383
@Override
369384
public Mono<Boolean> grantPermission(String applicationId,
370385
Set<String> userIds,
@@ -540,6 +555,7 @@ private ApplicationInfoView buildView(Application application, String role, @Nul
540555
.publicToAll(application.isPublicToAll())
541556
.publicToMarketplace(application.isPublicToMarketplace())
542557
.agencyProfile(application.agencyProfile())
558+
.editingUserId(application.getEditingUserId())
543559
.build();
544560
}
545561

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/application/ApplicationController.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,13 @@ public Mono<ResponseView<ApplicationView>> publish(@PathVariable String applicat
142142
.map(ResponseView::success);
143143
}
144144

145+
@Override
146+
public Mono<ResponseView<Boolean>> updateEditState(@PathVariable String applicationId, @RequestBody UpdateEditStateRequest updateEditStateRequest) {
147+
String appId = gidService.convertApplicationIdToObjectId(applicationId);
148+
return applicationApiService.updateEditState(appId, updateEditStateRequest)
149+
.map(ResponseView::success);
150+
}
151+
145152
@Override
146153
public Mono<ResponseView<UserHomepageView>> getUserHomePage(@RequestParam(required = false, defaultValue = "0") int applicationType) {
147154
ApplicationType type = ApplicationType.fromValue(applicationType);

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/application/ApplicationEndpoints.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,16 @@ public Mono<ResponseView<ApplicationView>> update(@PathVariable String applicati
137137
@PostMapping("/{applicationId}/publish")
138138
public Mono<ResponseView<ApplicationView>> publish(@PathVariable String applicationId);
139139

140+
@Operation(
141+
tags = TAG_APPLICATION_MANAGEMENT,
142+
operationId = "updateApplicationEditingState",
143+
summary = "Update Application editing state",
144+
description = "Update the editing state of a specific Lowcoder Application identified by its ID."
145+
)
146+
@PutMapping("/editState/{applicationId}")
147+
public Mono<ResponseView<Boolean>> updateEditState(@PathVariable String applicationId,
148+
@RequestBody UpdateEditStateRequest updateEditStateRequest);
149+
140150
@Operation(
141151
tags = TAG_APPLICATION_MANAGEMENT,
142152
operationId = "getUserHomepageApplication",
@@ -285,5 +295,7 @@ public record CreateApplicationRequest(@JsonProperty("orgId") String organizatio
285295
Map<String, Object> editingApplicationDSL,
286296
@Nullable String folderId) {
287297
}
298+
public record UpdateEditStateRequest(Boolean editingFinished) {
299+
}
288300

289301
}

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/application/view/ApplicationInfoView.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ public class ApplicationInfoView {
3838
private final boolean publicToMarketplace;
3939
private final boolean agencyProfile;
4040

41+
private final String editingUserId;
42+
4143
public long getLastViewTime() {
4244
return lastViewTime == null ? 0 : lastViewTime.toEpochMilli();
4345
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy