Skip to content

Commit

Permalink
feat: support selecting groups to join when link (#165)
Browse files Browse the repository at this point in the history
fixes #152
```release-note
S3关联时支持选择加入的分组
```
![image](https://github.com/user-attachments/assets/2380688c-3e04-4485-986d-b9118e05fe95)
  • Loading branch information
longjuan authored Jul 31, 2024
1 parent d4df735 commit 97f653b
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 15 deletions.
6 changes: 6 additions & 0 deletions console/src/api/models/link-request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@
* @interface LinkRequest
*/
export interface LinkRequest {
/**
*
* @type {string}
* @memberof LinkRequest
*/
'groupName'?: string;
/**
*
* @type {Array<string>}
Expand Down
81 changes: 75 additions & 6 deletions console/src/views/S3Link.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script setup lang="ts">
import { computed, onMounted, ref, watch } from "vue";
import { computed, getCurrentInstance, onMounted, ref, watch } from "vue";
import {
IconCheckboxCircle,
IconRefreshLine,
Toast,
VButton,
Expand All @@ -12,25 +13,47 @@ import {
VModal,
VPageHeader,
VSpace,
VStatusDot,
VTag,
} from "@halo-dev/components";
import CarbonFolderDetailsReference from "~icons/carbon/folder-details-reference";
import IconErrorWarning from "~icons/ri/error-warning-line";
import { axiosInstance } from "@halo-dev/api-client";
import { axiosInstance, coreApiClient, type Group } from "@halo-dev/api-client";
import { S3LinkControllerApi } from "@/api";
import type { S3ListResult, LinkResultItem, Policy, ObjectVo } from "@/api";
const s3LinkControllerApi = new S3LinkControllerApi(undefined, axiosInstance.defaults.baseURL, axiosInstance);
const componentInstance = getCurrentInstance();
const t = (key: string) => {
// @ts-ignore
if (typeof componentInstance?.proxy?.$t === 'function') {
// @ts-ignore
return componentInstance.proxy.$t(key);
}
return key;
};
const selectedFiles = ref<string[]>([]);
const policyName = ref<string>("");
const page = ref(1);
const size = ref(50);
const selectedGroup = ref("")
const policyOptions = ref<{ label: string; value: string; attrs: any }[]>([{
label: "请选择存储策略",
value: "",
attrs: {disabled: true}
}]);
const defaultGroup = ref<Group>({
apiVersion: "",
kind: "",
metadata: {
name: "",
},
spec: {
displayName: t("core.attachment.common.text.ungrouped"),
},
});
// update when fetch first page
const filePrefix = ref<string>("");
// update when user input
Expand All @@ -43,6 +66,7 @@ const s3Objects = ref<S3ListResult>({
currentContinuationObject: "",
nextContinuationObject: "",
});
const customGroups = ref<Group[]>([]);
// view state
const isFetching = ref(false);
const isShowModal = ref(false);
Expand Down Expand Up @@ -91,7 +115,7 @@ const handleCheckAllChange = (e: Event) => {
const fetchPolicies = async () => {
try {
const {status, data} = await s3LinkControllerApi.listS3Policies();
if (status == 200) {
if (status === 200) {
policyOptions.value = [{
label: "请选择存储策略",
value: "",
Expand Down Expand Up @@ -174,7 +198,8 @@ const handleLink = async () => {
const linkResult = await s3LinkControllerApi.addAttachmentRecord({
linkRequest: {
policyName: policyName.value,
objectKeys: selectedFiles.value
objectKeys: selectedFiles.value,
groupName: selectedGroup.value,
}
});
const items = linkResult.data.items || [];
Expand Down Expand Up @@ -219,7 +244,20 @@ const handleModalClose = () => {
fetchObjects();
};
onMounted(fetchPolicies);
const fetchCustomGroups = async () => {
const {status, data} = await coreApiClient.storage.group.listGroup({
labelSelector: ["!halo.run/hidden"],
sort: ["metadata.creationTimestamp,asc"],
});
if (status === 200) {
customGroups.value = data.items;
}
};
onMounted(() => {
fetchPolicies();
fetchCustomGroups();
});
watch(selectedFiles, (newValue) => {
checkedAll.value = s3Objects.value.objects?.filter(file => !file.isLinked)
Expand All @@ -232,7 +270,7 @@ watch(selectedLinkedStatusItem, handleFirstPage);
</script>

<template>
<VPageHeader title="关联S3文件(Beta)">
<VPageHeader title="关联S3文件">
<template #icon>
<CarbonFolderDetailsReference class="mr-2 self-center"/>
</template>
Expand Down Expand Up @@ -327,6 +365,37 @@ watch(selectedLinkedStatusItem, handleFirstPage);
class="box-border h-full w-full divide-y divide-gray-100"
role="list"
>
<li style="padding: 0.5rem 1rem 0">
<span class="ml-1 mb-1 block text-sm text-gray-500">关联后所加入的分组</span>
<div class="mb-5 grid grid-cols-2 gap-x-2 gap-y-3 md:grid-cols-3 lg:grid-cols-4 2xl:grid-cols-6">
<button
type="button"
class="inline-flex h-full w-full items-center gap-2 rounded-md border border-gray-200 bg-white px-3 py-2.5 text-sm font-medium text-gray-800 hover:bg-gray-50 hover:shadow-sm"
v-for="(group, index) in [defaultGroup, ...customGroups]"
:key="index"
:class="{ '!bg-gray-100 shadow-sm': group.metadata.name === selectedGroup }"
@click="selectedGroup = group.metadata.name"
>
<div class="inline-flex w-full flex-1 gap-x-2 break-all text-left">
<slot name="text">
{{ group?.spec.displayName }}
</slot>
<VStatusDot
v-if="group?.metadata.deletionTimestamp"
v-tooltip="$t('core.common.status.deleting')"
state="warning"
animate
/>
</div>
<div class="flex-none">
<IconCheckboxCircle
v-if="group.metadata.name === selectedGroup"
class="text-primary"
/>
</div>
</button>
</div>
</li>
<li v-for="(file, index) in s3Objects.objects" :key="index">
<VEntity :is-selected="checkSelection(file)">
<template
Expand Down
1 change: 1 addition & 0 deletions src/main/java/run/halo/s3os/LinkRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@
public class LinkRequest {
private String policyName;
private Set<String> objectKeys;
private String groupName;
}
2 changes: 1 addition & 1 deletion src/main/java/run/halo/s3os/S3LinkController.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,6 @@ public Mono<S3ListResult> listObjects(@PathVariable(value = "policyName") String
@PostMapping("/attachments/link")
public Mono<LinkResult> addAttachmentRecord(@RequestBody LinkRequest linkRequest) {
return s3LinkService.addAttachmentRecords(linkRequest.getPolicyName(),
linkRequest.getObjectKeys());
linkRequest.getObjectKeys(), linkRequest.getGroupName());
}
}
8 changes: 5 additions & 3 deletions src/main/java/run/halo/s3os/S3LinkService.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ public interface S3LinkService {
Flux<Policy> listS3Policies();

Mono<S3ListResult> listObjects(String policyName, String continuationToken,
Integer pageSize, String filePrefix);
Integer pageSize, String filePrefix);

Mono<LinkResult> addAttachmentRecords(String policyName, Set<String> objectKeys);
Mono<LinkResult> addAttachmentRecords(String policyName, Set<String> objectKeys,
String groupName);

Mono<S3ListResult> listObjectsUnlinked(String policyName, String continuationToken,
String continuationObject, Integer pageSize, String filePrefix);
String continuationObject, Integer pageSize,
String filePrefix);
}
14 changes: 9 additions & 5 deletions src/main/java/run/halo/s3os/S3LinkServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,11 @@ public Mono<S3ListResult> listObjects(String policyName, String continuationToke
}

@Override
public Mono<LinkResult> addAttachmentRecords(String policyName, Set<String> objectKeys) {
public Mono<LinkResult> addAttachmentRecords(String policyName, Set<String> objectKeys, String groupName) {
return getOperableObjectKeys(objectKeys, policyName)
.flatMap(operableObjectKeys -> getExistingAttachments(objectKeys, policyName)
.flatMap(existingAttachments -> getLinkResultItems(objectKeys, operableObjectKeys,
existingAttachments, policyName)
existingAttachments, policyName, groupName)
.collectList()
.map(LinkResult::new)));
}
Expand Down Expand Up @@ -147,12 +147,13 @@ private Mono<Set<String>> getExistingAttachments(Set<String> objectKeys,
private Flux<LinkResult.LinkResultItem> getLinkResultItems(Set<String> objectKeys,
Set<String> operableObjectKeys,
Set<String> existingAttachments,
String policyName) {
String policyName,
String groupName) {
return Flux.fromIterable(objectKeys)
.flatMap((objectKey) -> {
if (operableObjectKeys.contains(objectKey) &&
!existingAttachments.contains(objectKey)) {
return addAttachmentRecord(policyName, objectKey)
return addAttachmentRecord(policyName, objectKey, groupName)
.onErrorResume((throwable) -> Mono.just(
new LinkResult.LinkResultItem(objectKey, false,
throwable.getMessage())));
Expand Down Expand Up @@ -223,7 +224,7 @@ record TokenState(String currToken, String nextToken) {
}

public Mono<LinkResult.LinkResultItem> addAttachmentRecord(String policyName,
String objectKey) {
String objectKey, String groupName) {
return authenticationConsumer(authentication -> client.fetch(Policy.class, policyName)
.flatMap((policy) -> {
var configMapName = policy.getSpec().getConfigMapName();
Expand Down Expand Up @@ -255,6 +256,9 @@ public Mono<LinkResult.LinkResultItem> addAttachmentRecord(String policyName,
}
spec.setOwnerName(authentication.getName());
spec.setPolicyName(policyName);
if (StringUtils.isNotBlank(groupName)){
spec.setGroupName(groupName);
}
})
.flatMap(client::create)
.thenReturn(new LinkResult.LinkResultItem(objectKey, true, null));
Expand Down

0 comments on commit 97f653b

Please sign in to comment.