Skip to content

Commit 9cd4957

Browse files
authored
Update space cover image (#210)
* Remove not used const variable * Optimize new space form page * Locale for space replace cover image * Handle cover image upload for space settings page * Show cover image on space settings * Update space cover image to server * Support update space cover image * Update cover image * Remove previous image url when remove image * Create el_upload icon * Refactor code format
1 parent 751b51a commit 9cd4957

File tree

8 files changed

+99
-6
lines changed

8 files changed

+99
-6
lines changed

app/controllers/internal_api/application_spaces_controller.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ def update
5252
@application_space.nickname = params[:nickname] if params[:nickname].present?
5353
@application_space.desc = params[:desc] if params[:desc].present?
5454
@application_space.cloud_resource = params[:cloud_resource] if params[:cloud_resource].present?
55+
@application_space.cover_image = params[:cover_image] if params[:cover_image].present?
5556

5657
if @application_space.save
5758
render json: { message: I18n.t('repo.updateSuccess') }

app/javascript/components/application_spaces/ApplicationSpaceSettings.vue

Lines changed: 84 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,47 @@
196196

197197
<el-divider/>
198198

199+
<!-- cover image -->
200+
<div class="flex xl:flex-col gap-[32px]">
201+
<div class="w-[380px] sm:w-full flex flex-col">
202+
<div class="text-[14px] text-[#344054] leading-[20px] font-medium">
203+
{{ $t('application_spaces.edit.replaceCoverImage')}}
204+
</div>
205+
</div>
206+
<div class="flex flex-col gap-[6px] w-[400px] sm:w-[98%]">
207+
<el-upload
208+
:class="`${hideImageUploadElement ? 'hide' : 'h-auto' }`"
209+
:limit="1"
210+
v-model:file-list="images"
211+
list-type="picture-card"
212+
:headers="{ 'X-CSRF-TOKEN': csrfToken }"
213+
accept="image/png, image/jpeg, image/gif, image/svg+xml"
214+
:data="{namespace: 'application_space'}"
215+
action="/internal_api/upload"
216+
:before-upload="handleBeforeUpload"
217+
:on-remove="handleRemoveImage"
218+
:on-success="handleUploadSuccess"
219+
>
220+
<div class="flex flex-col items-center">
221+
<SvgIcon name="el_upload" width="20" height="18" />
222+
<div class="el-upload__text">
223+
<div>
224+
{{ $t('application_spaces.new.coverImageDesc1') }}
225+
</div>
226+
<div class="font-light text-[12px]">
227+
{{ $t('application_spaces.new.coverImageDesc2') }}
228+
</div>
229+
</div>
230+
</div>
231+
</el-upload>
232+
<el-button @click="updateApplicationSpaceCoverImage" class="w-[100px]">
233+
{{ $t('all.update')}}
234+
</el-button>
235+
</div>
236+
</div>
237+
238+
<el-divider/>
239+
199240
<!-- 删除应用空间 -->
200241
<div class="flex xl:flex-col gap-[32px]">
201242
<div class="w-[380px] sm:w-full flex flex-col gap-[6px]">
@@ -247,6 +288,7 @@ import refreshJWT from '../../packs/refreshJWT.js'
247288
import jwtFetch from '../../packs/jwtFetch'
248289
import useRepoDetailStore from '../../stores/RepoDetailStore'
249290
import { mapState, mapWritableState, mapActions } from 'pinia'
291+
import { useI18n } from 'vue-i18n'
250292
251293
export default {
252294
props: {
@@ -255,7 +297,8 @@ export default {
255297
applicationSpaceDesc: String,
256298
default_branch: String,
257299
appStatus: String,
258-
cloudResource: String
300+
cloudResource: String,
301+
coverImage: String
259302
},
260303
261304
components: {},
@@ -274,13 +317,21 @@ export default {
274317
initialized: ['Building', 'Deploying', 'Startup', 'Running', 'Stopped', 'Sleeping', 'BuildingFailed', 'DeployFailed', 'RuntimeError'].includes(this.appStatus),
275318
notInitialized: this.appStatus === 'NoAppFile',
276319
cookies: useCookies().cookies,
277-
csghubServer: inject('csghubServer')
320+
csghubServer: inject('csghubServer'),
321+
images: [{name: 'default', url: (this.coverImage || "/images/default_cover_image.png")}],
322+
uploadCoverImageUrl: '/images/default_cover_image.png',
323+
imageUploaded: false,
324+
csrfToken: document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
325+
t: useI18n()
278326
};
279327
},
280328
281329
computed: {
282330
...mapState(useRepoDetailStore, ['isPrivate']),
283331
...mapWritableState(useRepoDetailStore, ['privateVisibility']),
332+
hideImageUploadElement() {
333+
return (this.imageUploaded || this.images.length !== 0)
334+
},
284335
visibilityName: {
285336
get() {
286337
return !!this.privateVisibility ? 'Private' : 'Public'
@@ -303,6 +354,25 @@ export default {
303354
methods: {
304355
...mapActions(useRepoDetailStore, ['updateVisibility']),
305356
357+
handleBeforeUpload(file) {
358+
if (file.size / 1024 <= 2000) {
359+
return true
360+
} else {
361+
ElMessage({message: this.t('all.fileTooLarge'), type: "warning"})
362+
return false
363+
}
364+
},
365+
366+
handleRemoveImage() {
367+
this.uploadCoverImageUrl = ''
368+
this.imageUploaded = false
369+
},
370+
371+
handleUploadSuccess(res) {
372+
this.uploadCoverImageUrl = res.url
373+
this.imageUploaded = true
374+
},
375+
306376
clickDelete() {
307377
if (this.delDesc === this.applicationSpacePath) {
308378
this.deleteApplicationSpace().catch((err) => {
@@ -476,6 +546,11 @@ export default {
476546
this.updateApplicationSpace(payload)
477547
},
478548
549+
updateApplicationSpaceCoverImage() {
550+
const payload = {cover_image: this.uploadCoverImageUrl}
551+
this.updateApplicationSpace(payload)
552+
},
553+
479554
async updateApplicationSpace(payload) {
480555
const applicationSpaceUpdateEndpoint = "/internal_api/spaces/" + this.path
481556
const options = {
@@ -513,4 +588,10 @@ export default {
513588
}
514589
}
515590
}
516-
</script>
591+
</script>
592+
593+
<style scoped>
594+
:deep(.hide .el-upload.el-upload--picture-card){
595+
display: none;
596+
}
597+
</style>

app/javascript/components/application_spaces/NewApplicationSpace.vue

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
<template>
22
<div class="w-[640px] m-auto flex flex-col items-center md:w-full md:p-5">
33
<div>
4-
<SvgIcon width="36" height="36" name="spaces" />
4+
<SvgIcon name="spaces" width="36" height="36" />
55
</div>
66
<h3 class="text-[#303133] text-xl font-semibold mt-6 mb-3">{{ $t('application_spaces.new.title') }}</h3>
77
<p class="text-[#606266] text-base font-medium md:text-center">{{ $t('application_spaces.new.subTitle1') }}</p>
88
<p class="text-[#606266] text-base font-medium md:text-center">{{ $t('application_spaces.new.subTitle2') }}</p>
99
<div class="mt-9">
10+
<!-- name -->
1011
<div class="w-full flex sm:flex-col gap-2 mb-9 md:gap-9">
1112
<div>
1213
<p class="text-[#303133] text-sm mb-2">{{ $t('application_spaces.new.owner') }}</p>
@@ -32,6 +33,7 @@
3233
</div>
3334
</div>
3435

36+
<!-- nickname & license -->
3537
<div class="w-full flex sm:flex-col gap-2 mb-9 md:gap-9">
3638
<div class="flex-1">
3739
<p class="text-[#303133] text-sm mb-2">{{ $t('application_spaces.new.nickname') }}</p>
@@ -49,6 +51,7 @@
4951
</div>
5052
</div>
5153

54+
<!-- desc -->
5255
<div class="w-full flex sm:flex-col mb-9">
5356
<div class="flex-1">
5457
<p class="text-[#303133] text-sm mb-2">{{ $t('application_spaces.new.description') }}</p>
@@ -192,7 +195,6 @@
192195
const SDK = ref('gradio')
193196
const images = ref([])
194197
const coverImage = ref('')
195-
const prefixPath = document.location.pathname.split('/')[1]
196198
const csrf_token = document.querySelector('meta[name="csrf-token"]').getAttribute('content')
197199
const hasCreateApplicationSpace = ref(false)
198200

app/javascript/components/shared/RepoTabs.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@
121121
:default_branch="repoDetail.default_branch"
122122
:appStatus="appStatus"
123123
:cloudResource="repoDetail.hardware"
124+
:coverImage="repoDetail.cover_image_url"
124125
@showSpaceLogs="showSpaceLogs" />
125126
<code-settings
126127
v-if="repoType === 'code'"

app/models/application_space.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ def update_starhub_server_application_space
3939
desc,
4040
{ private: application_space_private?,
4141
current_user: creator&.name,
42-
hardware: cloud_resource
42+
hardware: cloud_resource,
43+
cover_image_url: cover_image
4344
})
4445
raise StarhubError, res.body unless res.success?
4546
end

config/locales/en_js/application_spaces.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ export const application_spaces = {
9999
publicInfo: ", visible to anyone on the internet.",
100100
needName: "Please provide name first",
101101
needDesc: "Please provide description first",
102+
replaceCoverImage: "Replace the cover image"
102103
},
103104
download: "Download Space",
104105
downloadSpace: "Download space data",

config/locales/zh_js/application_spaces.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ export const application_spaces = {
9898
publicInfo: ", 任何互联网上的人都可以看到此应用空间。",
9999
needName: "请先提供应用空间别名",
100100
needDesc: "请先提供应用空间介绍",
101+
replaceCoverImage: "更新封面图片"
101102
},
102103
download: "下载应用空间",
103104
downloadSpace: "下载应用空间数据",

public/images/icons/el_upload.svg

Lines changed: 5 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)