Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support selecting groups to join when link #165

Merged
merged 4 commits into from
Jul 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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