diff --git a/client/packages/lowcoder-design/src/icons/icon-comment-comp.svg b/client/packages/lowcoder-design/src/icons/icon-comment-comp.svg new file mode 100644 index 000000000..b6828e6a0 --- /dev/null +++ b/client/packages/lowcoder-design/src/icons/icon-comment-comp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/client/packages/lowcoder-design/src/icons/index.ts b/client/packages/lowcoder-design/src/icons/index.ts index 623486ade..4be847768 100644 --- a/client/packages/lowcoder-design/src/icons/index.ts +++ b/client/packages/lowcoder-design/src/icons/index.ts @@ -292,7 +292,8 @@ export { ReactComponent as CompressIcon } from "icons/icon-compress.svg"; export { ReactComponent as TableCellsIcon } from "icons/icon-table-cells.svg"; // Added By Aqib Mirza export { ReactComponent as TimeLineIcon } from "icons/icon-timeline-comp.svg" export { ReactComponent as LottieIcon } from "icons/icon-lottie.svg"; +export { ReactComponent as CommentIcon } from "icons/icon-comment-comp.svg"; export { ReactComponent as MentionIcon } from "icons/icon-mention-comp.svg"; export { ReactComponent as AutoCompleteCompIcon } from "icons/icon-autocomplete-comp.svg"; export { ReactComponent as WidthIcon } from "icons/icon-width.svg"; -export { ReactComponent as ResponsiveLayoutCompIcon } from "icons/icon-responsive-layout-comp.svg"; +export { ReactComponent as ResponsiveLayoutCompIcon } from "icons/icon-responsive-layout-comp.svg"; \ No newline at end of file diff --git a/client/packages/lowcoder/package.json b/client/packages/lowcoder/package.json index 8d71c0af4..3e5579d0d 100644 --- a/client/packages/lowcoder/package.json +++ b/client/packages/lowcoder/package.json @@ -44,7 +44,7 @@ "antd-img-crop": "^4.12.2", "axios": "^0.21.1", "buffer": "^6.0.3", - "clsx": "^1.2.1", + "clsx": "^2.0.0", "cnchar": "^3.2.4", "copy-to-clipboard": "^3.3.3", "core-js": "^3.25.2", diff --git a/client/packages/lowcoder/src/comps/comps/commentComp/commentComp.tsx b/client/packages/lowcoder/src/comps/comps/commentComp/commentComp.tsx new file mode 100644 index 000000000..74168ec9e --- /dev/null +++ b/client/packages/lowcoder/src/comps/comps/commentComp/commentComp.tsx @@ -0,0 +1,412 @@ +import React, { useEffect, useState, useRef } from "react"; +// 渲染组件到编辑器 +import { + changeChildAction, + CompAction, + RecordConstructorToView, +} from "lowcoder-core"; +// 文字国际化转换api +import { trans } from "i18n"; +// 右侧属性栏总框架 +import { UICompBuilder, withDefault } from "../../generators"; +// 右侧属性子框架 +import { Section, sectionNames } from "lowcoder-design"; +// 指示组件是否隐藏的开关 +import { hiddenPropertyView } from "comps/utils/propertyUtils"; +// 右侧属性开关 + +import { BoolControl } from "comps/controls/boolControl"; +import { styleControl } from "comps/controls/styleControl"; //样式输入框 +import { jsonValueExposingStateControl } from "comps/controls/codeStateControl"; +import { jsonControl, StringControl } from "comps/controls/codeControl"; +// 事件控制 +import { + clickEvent, + submitEvent, + eventHandlerControl, + deleteEvent, + mentionEvent, +} from "comps/controls/eventHandlerControl"; + +// 引入样式 +import { + CommentStyle, + heightCalculator, + widthCalculator, +} from "comps/controls/styleControlConstants"; +// 初始化暴露值 +import { stateComp, valueComp } from "comps/generators/simpleGenerators"; +// 组件对外暴露属性的api +import { + NameConfig, + NameConfigHidden, + withExposingConfigs, +} from "comps/generators/withExposing"; + +import { + commentDate, + commentDataTYPE, + CommentDataTooltip, + CommentUserDataTooltip, + convertCommentData, + checkUserInfoData, + checkMentionListData, +} from "./commentConstants"; +import { Avatar, List, Button, Mentions, Tooltip } from "antd"; +import VirtualList, { ListRef } from "rc-virtual-list"; +import _ from "lodash"; +import relativeTime from "dayjs/plugin/relativeTime"; +import dayjs from "dayjs"; +import "dayjs/locale/zh-cn"; +import { getInitialsAndColorCode } from "util/stringUtils"; +import { CloseOutlined } from "@ant-design/icons"; +dayjs.extend(relativeTime); +dayjs.locale("zh-cn"); + +const EventOptions = [ + clickEvent, + submitEvent, + deleteEvent, + mentionEvent, +] as const; + +const childrenMap = { + value: jsonControl(convertCommentData, commentDate), + title: withDefault(StringControl, trans("comment.titledDefaultValue")), + placeholder: withDefault(StringControl, trans("comment.placeholder")), + buttonText: withDefault(StringControl, trans("comment.buttonText")), + sendCommentAble: BoolControl.DEFAULT_TRUE, + deleteAble: BoolControl, + userInfo: jsonControl(checkUserInfoData, { + name: "{{currentUser.name}}", + email: "{{currentUser.email}}", + }), + mentionList: jsonControl(checkMentionListData, { + "@": ["Li Lei", "Han Meimei"], + "#": ["123", "456", "789"], + }), + onEvent: eventHandlerControl(EventOptions), + style: styleControl(CommentStyle), + commentList: jsonValueExposingStateControl("commentList", []), + deletedItem: jsonValueExposingStateControl("deletedItem", []), + submitedItem: jsonValueExposingStateControl("submitedItem", []), + mentionName: valueComp(""), +}; + +const CommentCompBase = ( + props: RecordConstructorToView & { + dispatch: (action: CompAction) => void; + } +) => { + // const VirtualListRef = useRef(null); + const divRef = useRef(null); + const { + value, + dispatch, + style, + title, + sendCommentAble, + buttonText, + onEvent, + mentionList, + userInfo, + placeholder, + deleteAble, + } = props; + type PrefixType = "@" | keyof typeof mentionList; + // 用于保存整合后的提及列表 + const [MentionListData, setMentionList] = useState([]); + const [commentListData, setCommentListData] = useState([]); + const [prefix, setPrefix] = useState("@"); + const [context, setContext] = useState(""); + // 将评论列表与原提及列表中的名字进行整合 + const mergeAllMentionList = (mentionList: any) => { + setMentionList( + _.merge(mentionList, { + "@": _.union( + _.concat( + mentionList["@"], + _.map(commentListData, (item, index) => { + return item?.user?.name; + }) + ) + ), + }) + ); + }; + useEffect(() => { + setCommentListData(value); + }, [value]); + + useEffect(() => { + mergeAllMentionList(mentionList); + }, [mentionList]); + + useEffect(() => { + props.commentList.onChange(commentListData); + mergeAllMentionList(mentionList); + // Used to scroll the list to the bottom after submission + setTimeout(() => { + // VirtualListRef?.current?.scrollTo(999999); + if (divRef.current) divRef.current.scrollTop = 999999; + }, 50); + }, [commentListData]); + + // 获取提及搜索关键字 + const onSearch = (_: string, newPrefix: PrefixType) => { + setPrefix(newPrefix); + }; + // 生成评论头像 + const generateCommentAvatar = (item: commentDataTYPE) => { + return ( + props.onEvent("click")} + // 如果有头像,则不设置背景色,如果displayName不为空,则使用getInitialsAndColorCode调用displayName + style={{ + backgroundColor: item?.user?.avatar + ? "" + : getInitialsAndColorCode( + item?.user?.displayName === undefined + ? item?.user?.name + : item?.user?.displayName + )[1], + verticalAlign: "middle", + }} + src={item?.user?.avatar} + > + {" "} + {item?.user?.displayName + ? item?.user?.displayName + : /^([\u4e00-\u9fa5]{2,4})$/gi.test(item?.user?.name) + ? item?.user?.name.slice(-2) + : item?.user?.name[0]} + + ); + }; + const onChange = (value: string) => { + setContext(value); + }; + + const handleSubmit = () => { + let subObject = { + user: userInfo, + value: context, + createdAt: dayjs().format(), + }; + props.submitedItem.onChange(subObject); + setCommentListData(_.concat(commentListData, [subObject])); + setContext(""); + mergeAllMentionList(mentionList); + props.onEvent("submit"); + }; + + const handleDelete = (index: number) => { + let temp = _.cloneDeep(commentListData); + props.deletedItem.onChange(temp.splice(index, 1)); + setCommentListData(temp); + props.onEvent("delete"); + }; + + const onPressEnter = (e: any) => { + if (e.shiftKey) { + e.preventDefault(); + handleSubmit(); + } + }; + return ( +
+
+ + {commentListData.length > 1 + ? title + .replaceAll("%d", commentListData.length.toString()) + .replace("comment", "comments") + : title.replaceAll("%d", commentListData.length.toString())} +
+ ) : ( + "" + ) + } + size="small" + > + + {(item, index) => ( + handleDelete(index)} + />, + ] + : undefined + } + > + props.onEvent("click")}> + {item?.user?.name} + + + {dayjs(item?.createdAt).isValid() + ? dayjs(item?.createdAt).fromNow() + : trans("comment.dateErr")} + + +
+ } + description={{item?.value}} + /> + + )} + + + {sendCommentAble ? ( +
+ { + dispatch(changeChildAction("mentionName", option?.value, false)); + props.onEvent("mention"); + }} + value={context} + rows={2} + onPressEnter={onPressEnter} + placeholder={placeholder} + > + {(MentionListData[prefix] || []).map( + (value: string, index: number) => ( + + {value} + + ) + )} + + +
+ ) : ( + "" + )} + + + ); +}; + +let CommentBasicComp = (function () { + return new UICompBuilder(childrenMap, (props, dispatch) => ( + + )) + .setPropertyViewFn((children) => ( + <> +
+ {children.title.propertyView({ + label: trans("comment.title"), + })} + {children.value.propertyView({ + label: trans("comment.value"), + tooltip: CommentDataTooltip, + placeholder: "[]", + })} + {children.userInfo.propertyView({ + label: trans("comment.userInfo"), + tooltip: CommentUserDataTooltip, + })} + {children.mentionList.propertyView({ + label: trans("comment.mentionList"), + tooltip: trans("comment.mentionListDec"), + })} + {children.sendCommentAble.propertyView({ + label: trans("comment.showSendButton"), + })} + {children.sendCommentAble.getView() && + children.buttonText.propertyView({ + label: trans("comment.buttonTextDec"), + })} + {children.placeholder.propertyView({ + label: trans("comment.placeholderDec"), + })} + {children.deleteAble.propertyView({ + label: trans("comment.deleteAble"), + })} +
+
+ {children.onEvent.getPropertyView()} + {hiddenPropertyView(children)} +
+
+ {children.style.getPropertyView()} +
+ + )) + .build(); +})(); + +CommentBasicComp = class extends CommentBasicComp { + override autoHeight(): boolean { + return false; + } +}; +export const CommentComp = withExposingConfigs(CommentBasicComp, [ + new NameConfig("commentList", trans("comment.commentList")), + new NameConfig("deletedItem", trans("comment.deletedItem")), + new NameConfig("submitedItem", trans("comment.submitedItem")), + new NameConfig("mentionName", trans("comment.submitedItem")), + NameConfigHidden, +]); diff --git a/client/packages/lowcoder/src/comps/comps/commentComp/commentConstants.tsx b/client/packages/lowcoder/src/comps/comps/commentComp/commentConstants.tsx new file mode 100644 index 000000000..ab4a71f40 --- /dev/null +++ b/client/packages/lowcoder/src/comps/comps/commentComp/commentConstants.tsx @@ -0,0 +1,106 @@ +import { trans } from "i18n"; +import { check } from "util/convertUtils"; + +export type userTYPE = { + name: string; + avatar?: string; + displayName?: string; + email?: string; +}; +export type commentDataTYPE = { + user: userTYPE; + value?: string; + createdAt?: string; +}; + +export type userInfoType = Record; + +export const CommentDataTooltip = ( +
  • + {trans("comment.Introduction")}: +
    + 1. user - {trans("comment.helpUser")} +
    +  .name - {trans("comment.helpname")} +
    +  .avatar - {trans("comment.helpavatar")} +
    +  .displayName - {trans("comment.helpdisplayName")} +
    + 2. value - {trans("comment.helpvalue")} +
    + 3. createdAt - {trans("comment.helpcreatedAt")} +
  • +); + +export const CommentUserDataTooltip = ( +
  • + {trans("comment.Introduction")}: +
    + 1.name - {trans("comment.helpname")} +
    + 2.avatar - {trans("comment.helpavatar")} +
    + 3.displayName - {trans("comment.helpdisplayName")} +
  • +) + +export const commentDate = [ + { + user: { + name: "Li Lei", + avatar: + "https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png", + }, + value: "What is the use of this component?", + createdAt: "2023-06-15T08:40:41.658Z", + }, + { + user: { name: "mou" }, + value: "This component allows you to post or delete comments, as well as mention people who appear in the chat.", + createdAt: "2023-06-16T08:43:42.658Z", + }, + { + user: { name: "Han Meimei", displayName: "Han" }, + value: "I want to give it a try", + createdAt: "2023-06-17T08:49:01.658Z", + }, + { + user: { name: "mou" }, + value: "Enter the content in the input box below and press shift+enter to send it immediately", + createdAt: "2023-06-18T08:50:11.658Z", + }, +]; + +export function convertCommentData(data: any) { + return data === "" ? [] : checkDataNodes(data) ?? []; +} + +function checkDataNodes( + value: any, + key?: string +): commentDataTYPE[] | undefined { + return check(value, ["array", "undefined"], key, (node, k) => { + check(node, ["object"], k); + check(node["user"], ["object"], "user"); + check(node["value"], ["string", "undefined"], "value"); + check(node["createdAt"], ["string", "undefined"], "createdAt"); + return node; + }); +} +export function checkUserInfoData(data: any) { + check(data?.name, ["string"], "name") + check(data?.avatar, ["string","undefined"], "avatar") + return data +} + +export function checkMentionListData(data: any) { + if(data === "") return {} + for(const key in data) { + check(data[key], ["array"], key,(node)=>{ + check(node, ["string"], ); + return node + }) + } + return data +} \ No newline at end of file diff --git a/client/packages/lowcoder/src/comps/controls/eventHandlerControl.tsx b/client/packages/lowcoder/src/comps/controls/eventHandlerControl.tsx index 29b3093de..854cfeef3 100644 --- a/client/packages/lowcoder/src/comps/controls/eventHandlerControl.tsx +++ b/client/packages/lowcoder/src/comps/controls/eventHandlerControl.tsx @@ -343,6 +343,11 @@ export const successEvent: EventConfigType = { value: "success", description: trans("event.successDesc"), }; +export const deleteEvent: EventConfigType = { + label: trans("event.delete"), + value: "delete", + description: trans("event.deleteDesc"), +}; export const mentionEvent: EventConfigType = { label: trans("event.mention"), value: "mention", diff --git a/client/packages/lowcoder/src/comps/controls/styleControlConstants.tsx b/client/packages/lowcoder/src/comps/controls/styleControlConstants.tsx index 646de9c6e..0344f21c9 100644 --- a/client/packages/lowcoder/src/comps/controls/styleControlConstants.tsx +++ b/client/packages/lowcoder/src/comps/controls/styleControlConstants.tsx @@ -891,7 +891,7 @@ export const SignatureStyle = [ PADDING, ] as const; -//Added by Aqib Mirza +// Added by Aqib Mirza export const LottieStyle = [ { name: "background", @@ -904,7 +904,18 @@ export const LottieStyle = [ PADDING, ] as const; ///////////////////// - +export const CommentStyle = [ + { + name: "background", + label: trans("style.background"), + depTheme: "canvas", + depType: DEP_TYPE.SELF, + transformer: toSelf, + }, + MARGIN, + PADDING, + RADIUS, +] as const export const ResponsiveLayoutRowStyle = [ ...BG_STATIC_BORDER_RADIUS, MARGIN, diff --git a/client/packages/lowcoder/src/comps/index.tsx b/client/packages/lowcoder/src/comps/index.tsx index b14d6a4b9..8aa9386b7 100644 --- a/client/packages/lowcoder/src/comps/index.tsx +++ b/client/packages/lowcoder/src/comps/index.tsx @@ -97,6 +97,7 @@ import { VideoCompIcon, TimeLineIcon, LottieIcon, + CommentIcon, MentionIcon, AutoCompleteCompIcon, ResponsiveLayoutCompIcon, @@ -132,6 +133,7 @@ import { RemoteCompInfo } from "types/remoteComp"; import { ScannerComp } from "./comps/buttonComp/scannerComp"; import { SignatureComp } from "./comps/signatureComp"; import { TimeLineComp } from "./comps/timelineComp/timelineComp"; +import { CommentComp } from "./comps/commentComp/commentComp"; import { MentionComp } from "./comps/textInputComp/mentionComp"; import { AutoCompleteComp } from "./comps/autoCompleteComp/autoCompleteComp"; //Added by Aqib Mirza @@ -917,6 +919,20 @@ const uiCompMap: Registry = { h: 55, }, }, + + comment: { + name: trans("uiComp.commentCompName"), + enName: "comment", + description: trans("uiComp.commentCompDesc"), + categories: ["dataDisplay"], + icon: CommentIcon, + keywords: trans("uiComp.commentCompKeywords"), + comp: CommentComp, + layoutInfo: { + w: 13, + h: 55, + } + }, mention: { name: trans("uiComp.mentionCompName"), enName: "mention", diff --git a/client/packages/lowcoder/src/comps/uiCompRegistry.ts b/client/packages/lowcoder/src/comps/uiCompRegistry.ts index 4868b6826..c48be999e 100644 --- a/client/packages/lowcoder/src/comps/uiCompRegistry.ts +++ b/client/packages/lowcoder/src/comps/uiCompRegistry.ts @@ -119,6 +119,7 @@ export type UICompType = | "signature" | "jsonLottie" //Added By Aqib Mirza | "timeline" + | "comment" | "mention" | "autocomplete" | "responsiveLayout"; diff --git a/client/packages/lowcoder/src/i18n/locales/en.ts b/client/packages/lowcoder/src/i18n/locales/en.ts index 12b67abf2..741743c69 100644 --- a/client/packages/lowcoder/src/i18n/locales/en.ts +++ b/client/packages/lowcoder/src/i18n/locales/en.ts @@ -272,6 +272,8 @@ export const en = { parseDesc: "Triggers on parse", success: "Success", successDesc: "Triggers on success", + delete: "Delete", + deleteDesc: "Triggers on delete", mention: "mention", mentionDesc: "Triggers on mention", }, @@ -887,6 +889,9 @@ export const en = { timelineCompName: "Time Line", timelineCompDesc: "Time Line", timelineCompKeywords: "", + commentCompName: "Comment", + commentCompDesc: "Comment", + commentCompKeywords: "", mentionCompName: "mention", mentionCompDesc: "mention", mentionCompKeywords: "", @@ -2622,6 +2627,31 @@ export const en = { clickedObjectDesc: "clicked item data", clickedIndexDesc: "clicked item index", }, + comment: { + value: "comment list data", + showSendButton: "Allowing Comments", + title: "title", + titledDefaultValue: "%d comment in total", + placeholder: "shift + enter to comment;Enter @ or # for quick input", + placeholderDec: "placeholder", + buttonTextDec: "button title", + buttonText: "comment", + mentionList: "mention list data", + mentionListDec: "key-Mention keywords;value-Mention list data", + userInfo: "user info", + dateErr: "date error", + commentList: "comment list", + deletedItem: "deleted item", + submitedItem: "submited item", + deleteAble: "show delete button", + Introduction: "Introduction keys", + helpUser: "user info(Required)", + helpname: "user name(Required)", + helpavatar: "avatar url(high priority)", + helpdisplayName: "display name(low priority)", + helpvalue: "Comment content", + helpcreatedAt: "create date", + }, mention: { mentionList: "mention list", }, diff --git a/client/packages/lowcoder/src/i18n/locales/zh.ts b/client/packages/lowcoder/src/i18n/locales/zh.ts index 3e3e7d6c2..b73d9752a 100644 --- a/client/packages/lowcoder/src/i18n/locales/zh.ts +++ b/client/packages/lowcoder/src/i18n/locales/zh.ts @@ -259,6 +259,8 @@ event: { parseDesc: "在解析时触发", success: "成功", successDesc: "在成功时触发", + delete: "删除", + deleteDesc: "在删除时触发", mention: "提及", mentionDesc: "在提及时触发", }, @@ -835,6 +837,9 @@ uiComp: { timelineCompName: "时间线", timelineCompDesc: "时间线组件", timelineCompKeywords: "sjx", + commentCompName: "评论", + commentCompDesc: "评论组件", + commentCompKeywords: "pl", mentionCompName: "提及", mentionCompDesc: "提及组件", mentionCompKeywords: "tj", @@ -2479,6 +2484,31 @@ timeLine: { endlessLoop: "循环播放", keepLastFrame: "冻结最后一帧", }, + comment: { + value: "评论列表数据", + showSendButton: "允许评论", + title: "标题", + titledDefaultValue: "共有%d条评论", + placeholder: "shift + enter 快捷发送评论;输入@或#可快速输入", + placeholderDec: "占位符", + buttonTextDec: "按钮文本", + buttonText: "发表", + mentionList: "提及列表数据", + mentionListDec: "key-提及关键字;value-提及列表", + userInfo: "用户信息", + dateErr: "日期错误", + commentList: "评论列表数据", + deletedItem: "已删除的数据", + submitedItem: "已提交的数据", + deleteAble: "显示删除按钮", + Introduction: "属性介绍", + helpUser: "用户信息(必填)", + helpname: "用户名(必填)", + helpavatar: "头像地址(高优先)", + helpdisplayName: "头像文字(低优先)", + helpvalue: "评论内容", + helpcreatedAt: "创建时间", + }, mention:{ mentionList: "提及列表", }, diff --git a/client/packages/lowcoder/src/pages/editor/editorConstants.tsx b/client/packages/lowcoder/src/pages/editor/editorConstants.tsx index 2884b55ac..8baf2944d 100644 --- a/client/packages/lowcoder/src/pages/editor/editorConstants.tsx +++ b/client/packages/lowcoder/src/pages/editor/editorConstants.tsx @@ -38,6 +38,7 @@ import { LeftVideo, LeftSignature, TimeLineIcon, + CommentIcon, MentionIcon, AutoCompleteCompIcon, ResponsiveLayoutCompIcon, @@ -111,6 +112,7 @@ export const CompStateIcon: { signature: , jsonLottie: , //Added By Aqib Mirza timeline: , + comment: , mention: , autocomplete: , responsiveLayout: , diff --git a/client/yarn.lock b/client/yarn.lock index f8fd7fb9b..1ba2ab280 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -6255,13 +6255,20 @@ __metadata: languageName: node linkType: hard -"clsx@npm:^1.0.4, clsx@npm:^1.1.1, clsx@npm:^1.2.1": +"clsx@npm:^1.0.4, clsx@npm:^1.1.1": version: 1.2.1 resolution: "clsx@npm:1.2.1" checksum: 30befca8019b2eb7dbad38cff6266cf543091dae2825c856a62a8ccf2c3ab9c2907c4d12b288b73101196767f66812365400a227581484a05f968b0307cfaf12 languageName: node linkType: hard +"clsx@npm:^2.0.0": + version: 2.0.0 + resolution: "clsx@npm:2.0.0" + checksum: a2cfb2351b254611acf92faa0daf15220f4cd648bdf96ce369d729813b85336993871a4bf6978ddea2b81b5a130478339c20d9d0b5c6fc287e5147f0c059276e + languageName: node + linkType: hard + "cnchar-types@npm:^3.2.4": version: 3.2.4 resolution: "cnchar-types@npm:3.2.4" @@ -11994,7 +12001,7 @@ __metadata: antd-img-crop: ^4.12.2 axios: ^0.21.1 buffer: ^6.0.3 - clsx: ^1.2.1 + clsx: ^2.0.0 cnchar: ^3.2.4 copy-to-clipboard: ^3.3.3 core-js: ^3.25.2 diff --git a/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/authentication/AuthenticationController.java b/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/authentication/AuthenticationController.java index 7017da2fc..8f6a2cfcd 100644 --- a/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/authentication/AuthenticationController.java +++ b/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/authentication/AuthenticationController.java @@ -90,8 +90,8 @@ public Mono> enableAuthConfig(@RequestBody AuthConfigRequest } @DeleteMapping("/config/{id}") - public Mono> disableAuthConfig(@PathVariable("id") String id) { - return authenticationApiService.disableAuthConfig(id) + public Mono> disableAuthConfig(@PathVariable("id") String id, @RequestParam(required = false) boolean delete) { + return authenticationApiService.disableAuthConfig(id, delete) .thenReturn(ResponseView.success(null)); } diff --git a/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/authentication/service/AuthenticationApiService.java b/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/authentication/service/AuthenticationApiService.java index c3db123f0..68ac9f691 100644 --- a/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/authentication/service/AuthenticationApiService.java +++ b/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/authentication/service/AuthenticationApiService.java @@ -17,7 +17,7 @@ public interface AuthenticationApiService { Mono enableAuthConfig(AuthConfigRequest authConfigRequest); - Mono disableAuthConfig(String authId); + Mono disableAuthConfig(String authId, boolean delete); Flux findAuthConfigs(boolean enableOnly); } diff --git a/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/authentication/service/AuthenticationApiServiceImpl.java b/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/authentication/service/AuthenticationApiServiceImpl.java index da0d58aff..2851e1070 100644 --- a/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/authentication/service/AuthenticationApiServiceImpl.java +++ b/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/authentication/service/AuthenticationApiServiceImpl.java @@ -41,6 +41,7 @@ import javax.annotation.Nullable; import java.util.*; import java.util.function.Function; +import java.util.function.Predicate; import java.util.stream.Collectors; import static org.lowcoder.sdk.exception.BizError.*; @@ -239,12 +240,12 @@ public Mono enableAuthConfig(AuthConfigRequest authConfigRequest) { } @Override - public Mono disableAuthConfig(String authId) { + public Mono disableAuthConfig(String authId, boolean delete) { return checkIfAdmin() .then(checkIfOnlyEffectiveCurrentUserConnections(authId)) .then(sessionUserService.getVisitorOrgMemberCache()) .flatMap(orgMember -> organizationService.getById(orgMember.getOrgId())) - .doOnNext(organization -> disableAuthConfig(organization, authId)) + .doOnNext(organization -> disableAuthConfig(organization, authId, delete)) .flatMap(organization -> organizationService.update(organization.getId(), organization)) .delayUntil(result -> { if (result) { @@ -309,13 +310,28 @@ private Mono checkIfOnlyEffectiveCurrentUserConnections(String authId) { .then(); } - private void disableAuthConfig(Organization organization, String authId) { - Optional.of(organization) - .map(Organization::getAuthConfigs) - .orElse(Collections.emptyList()) - .stream() - .filter(abstractAuthConfig -> Objects.equals(abstractAuthConfig.getId(), authId)) - .forEach(abstractAuthConfig -> abstractAuthConfig.setEnable(false)); + private void disableAuthConfig(Organization organization, String authId, boolean delete) { + + Predicate authConfigPredicate = abstractAuthConfig -> Objects.equals(abstractAuthConfig.getId(), authId); + + if(delete) { + List abstractAuthConfigs = Optional.of(organization) + .map(Organization::getAuthConfigs) + .orElse(Collections.emptyList()); + + abstractAuthConfigs.removeIf(authConfigPredicate); + + organization.getOrganizationDomain().setConfigs(abstractAuthConfigs); + + } else { + Optional.of(organization) + .map(Organization::getAuthConfigs) + .orElse(Collections.emptyList()).stream() + .filter(authConfigPredicate) + .forEach(abstractAuthConfig -> { + abstractAuthConfig.setEnable(false); + }); + } } /** diff --git a/server/api-service/pom.xml b/server/api-service/pom.xml index a6acfae30..5af501f1b 100644 --- a/server/api-service/pom.xml +++ b/server/api-service/pom.xml @@ -175,7 +175,7 @@ org.eclipse.jgit org.eclipse.jgit - 6.5.0.202303070854-r + 6.7.0.202309050840-r