CLASSROOMIO-T-211: Add a content-switcher in the landing page settings for banner
CLASSROOMIO-T-211: Remove business logic of uploading image CLASSROOMIO-T-211:Updated the UI of the landingpage settings Merge branch 'main' into CLASSROOMIO-T-211 CLASSROOMIO-T-211:Added a Content-switch in the landingpage settings Co-authored-by: Ifeanyi Nwosu <ifeanyi@digdippa.com> Co-authored-by: Rotimi Best <rotimiibitoyeemma@gmail.com> Merge-request: CLASSROOMIO-MR-97 Merged-by: Best Admin <best@digdippa.com>
This commit is contained in:
committed by
Space Cloud
co-authored by
Rotimi Best
parent
27b0284538
commit
b676993c2d
@@ -13,8 +13,6 @@
|
||||
import { course } from '$lib/components/Course/store';
|
||||
import { updateCourse, deleteCourse } from '$lib/utils/services/courses';
|
||||
import { currentOrgPath } from '$lib/utils/store/org';
|
||||
import { supabase } from '$lib/utils/functions/supabase';
|
||||
import { Loading } from 'carbon-components-svelte';
|
||||
import { isObject } from '$lib/utils/functions/isObject';
|
||||
import { lessons } from '../Lesson/store/lessons';
|
||||
import { currentOrg } from '$lib/utils/store/org';
|
||||
@@ -22,14 +20,11 @@
|
||||
import UploadWidget from '$lib/components/UploadWidget/index.svelte';
|
||||
import { handleOpenWidget } from '$lib/components/CourseLandingPage/store';
|
||||
|
||||
let uploadingImage = false;
|
||||
let isSaving = false;
|
||||
let fileInput;
|
||||
let isLoading = false;
|
||||
let isDeleting = false;
|
||||
let errors = {};
|
||||
let avatar;
|
||||
let imagebuffer;
|
||||
|
||||
// controls widget open and close
|
||||
function widgetControl() {
|
||||
@@ -120,7 +115,7 @@
|
||||
const {
|
||||
course_title,
|
||||
course_description,
|
||||
image,
|
||||
logo,
|
||||
tabs,
|
||||
grading,
|
||||
lesson_download,
|
||||
@@ -129,7 +124,7 @@
|
||||
await updateCourse($course.id, avatar, {
|
||||
title: course_title,
|
||||
description: course_description,
|
||||
logo: image,
|
||||
logo: logo,
|
||||
is_published,
|
||||
metadata: {
|
||||
...(isObject($course.metadata) ? $course.metadata : {}),
|
||||
@@ -141,7 +136,7 @@
|
||||
|
||||
$course.title = course_title;
|
||||
$course.description = course_description;
|
||||
$course.logo = image;
|
||||
$course.logo = logo;
|
||||
$course.is_published = is_published;
|
||||
$course.metadata = {
|
||||
...(isObject($course.metadata) ? $course.metadata : {}),
|
||||
@@ -163,7 +158,7 @@
|
||||
$settings = {
|
||||
course_title: course.title,
|
||||
course_description: course.description,
|
||||
image: course.logo,
|
||||
logo: course.logo,
|
||||
tabs: course.metadata.lessonTabsOrder || $settings.tabs,
|
||||
grading: course.metadata.grading,
|
||||
lesson_download: course.metadata.lessonDownload,
|
||||
@@ -199,7 +194,7 @@
|
||||
/>
|
||||
</span>
|
||||
{#if $handleOpenWidget.open}
|
||||
<UploadWidget />
|
||||
<UploadWidget bind:imageURL={$settings.logo} />
|
||||
{/if}
|
||||
</Column>
|
||||
|
||||
@@ -208,12 +203,9 @@
|
||||
<img
|
||||
style="min-width:280px; min-height:200px"
|
||||
alt="About us"
|
||||
src={$settings.image ? $settings.image : '/images/classroomio-course-img-template.jpg'}
|
||||
src={$settings.logo ? $settings.logo : '/images/classroomio-course-img-template.jpg'}
|
||||
class="mt-2 md:mt-0 w-[280px] h-[200px] rounded-md relative"
|
||||
/>
|
||||
{#if uploadingImage}
|
||||
<Loading withOverlay={true} small class="absolute top-0 w-[280px]" />
|
||||
{/if}
|
||||
</div>
|
||||
</Column>
|
||||
</Row>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
export const settings = writable({
|
||||
image: '',
|
||||
logo: '',
|
||||
course_title: '',
|
||||
course_description: '',
|
||||
grading: false,
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
<script lang="ts">
|
||||
import UploadWidget from '$lib/components/UploadWidget/index.svelte';
|
||||
import get from 'lodash/get';
|
||||
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
import pluralize from 'pluralize';
|
||||
import { page } from '$app/stores';
|
||||
import { landingPage } from './store';
|
||||
import { Loading } from 'carbon-components-svelte';
|
||||
import Notebook from 'carbon-icons-svelte/lib/Notebook.svelte'; //note
|
||||
import PresentationFile from 'carbon-icons-svelte/lib/PresentationFile.svelte'; // exercise
|
||||
import Video from 'carbon-icons-svelte/lib/Video.svelte'; //video
|
||||
@@ -26,7 +22,6 @@
|
||||
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
|
||||
import HtmlRender from '$lib/components/HTMLRender/HTMLRender.svelte';
|
||||
import { calDateDiff } from '$lib/utils/functions/date';
|
||||
import { handleOpenWidget } from './store';
|
||||
|
||||
export let editMode = false;
|
||||
export let courseData: Course;
|
||||
@@ -128,10 +123,6 @@
|
||||
startCoursePayment = true;
|
||||
}}
|
||||
/>
|
||||
|
||||
{#if $handleOpenWidget.open}
|
||||
<UploadWidget />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- Banner Image getEmbedId(videoUrl) -->
|
||||
@@ -161,9 +152,6 @@
|
||||
src={bannerImage ? bannerImage : '/images/classroomio-course-img-template.jpg'}
|
||||
class="mt-2 md:mt-0 rounded-md w-full h-full max-w-[500px] max-h-[400px] relative"
|
||||
/>
|
||||
{#if $landingPage.uploadingImage}
|
||||
<Loading withOverlay={true} small class="absolute top-0 w-full h-full" />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- <div
|
||||
|
||||
@@ -60,11 +60,6 @@ export const reviewsModalStore = writable({
|
||||
open: false
|
||||
});
|
||||
|
||||
export const landingPage = writable({
|
||||
uploadingImage: false,
|
||||
imageUrl: ''
|
||||
});
|
||||
|
||||
export let handleOpenWidget = writable({
|
||||
open: false
|
||||
});
|
||||
|
||||
@@ -132,11 +132,17 @@
|
||||
// Use default data in store if user hasn't added their own content to landing page
|
||||
function setDefault(landingpage) {
|
||||
if (landingpage && Object.keys(landingpage).length) {
|
||||
$landingPageSettings = landingpage;
|
||||
if (!landingpage?.header?.banner) {
|
||||
landingpage.header.banner = $landingPageSettings.header.banner;
|
||||
}
|
||||
|
||||
$landingPageSettings = {
|
||||
...landingpage
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
$: initPlyr(player, $landingPageSettings.header.video.link);
|
||||
$: initPlyr(player, $landingPageSettings.header?.banner?.video);
|
||||
$: setDefault(org.landingpage);
|
||||
</script>
|
||||
|
||||
@@ -155,7 +161,7 @@
|
||||
<header id="header" class="banner w-full h-[100vh] md:h-[90vh] mb-10 relative">
|
||||
<Navigation logo={org.avatar_url} orgName={org.name} disableSignup={true} />
|
||||
<div class="absolute h-[100vh] md:h-[90vh] top-0 w-full opacity-80 z-10 bg-white" />
|
||||
{#if $landingPageSettings.header.video.show}
|
||||
{#if $landingPageSettings.header.banner.show}
|
||||
<div class="flex items-center justify-center md:h-full py-2">
|
||||
<div
|
||||
class="md:w-11/12 lg:w-5/6 w-full flex items-center justify-center md:justify-between flex-col-reverse md:flex-row z-20 relative"
|
||||
@@ -185,24 +191,30 @@
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="w-5/6 md:w-1/2 md:max-w-[650px] flex">
|
||||
{#if isYouTubeLink($landingPageSettings.header.video.link)}
|
||||
{#if isYouTubeLink($landingPageSettings.header?.banner?.video) && $landingPageSettings.header.banner.type === 'video'}
|
||||
<div bind:this={player} id="player" style="width:100%; border-radius:12px">
|
||||
<iframe
|
||||
title="Header video"
|
||||
src={$landingPageSettings.header.video.link}
|
||||
src={$landingPageSettings.header?.banner?.video}
|
||||
allowfullscreen
|
||||
allowtransparency
|
||||
allow="autoplay"
|
||||
/>
|
||||
</div>
|
||||
{:else}
|
||||
<video class="w-full rounded-xl" controls loop autoplay>
|
||||
<source src={$landingPageSettings.header.video.link} type="video/mp4" />
|
||||
<!-- <source src="/path/to/video.webm" type="video/webm" /> -->
|
||||
<!-- Captions are optional -->
|
||||
<track kind="captions" />
|
||||
</video>
|
||||
<!-- <video class="w-full rounded-xl" controls loop autoplay>
|
||||
<source src={$landingPageSettings.header?.banner?.video} type="video/mp4" />
|
||||
<source src="/path/to/video.webm" type="video/webm" />
|
||||
Captions are optional
|
||||
<track kind="captions" />
|
||||
</video> -->
|
||||
<img
|
||||
class="rounded-md"
|
||||
src={$landingPageSettings.header?.banner?.image}
|
||||
alt="landing page banner"
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { Grid, Row, Column } from 'carbon-components-svelte';
|
||||
import { Grid, Row, Column, RadioButtonGroup, RadioButton } from 'carbon-components-svelte';
|
||||
import TrashCan from 'carbon-icons-svelte/lib/TrashCan.svelte';
|
||||
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
|
||||
import IconButton from '$lib/components/IconButton/index.svelte';
|
||||
@@ -14,13 +14,21 @@
|
||||
import { FileUploader } from 'carbon-components-svelte';
|
||||
import { landingPageSettings } from './store';
|
||||
import type { OrgLandingPageJson } from './store';
|
||||
import UploadWidget from '$lib/components/UploadWidget/index.svelte';
|
||||
import { handleOpenWidget } from '$lib/components/CourseLandingPage/store';
|
||||
import merge from 'lodash/merge';
|
||||
|
||||
let files: File[] = [];
|
||||
let imageBuffer: File;
|
||||
let uploadingImage = false;
|
||||
let isSaving = false;
|
||||
let creatingNewQuestion = false;
|
||||
let widgetKey = '';
|
||||
|
||||
const banner = [
|
||||
{ value: 'video', label: 'Video' },
|
||||
{ value: 'image', label: 'Image' }
|
||||
];
|
||||
const supabase = getSupabase();
|
||||
|
||||
let newQuestion = {
|
||||
@@ -28,6 +36,11 @@
|
||||
content: ''
|
||||
};
|
||||
|
||||
function widgetControl(key: string) {
|
||||
widgetKey = key;
|
||||
$handleOpenWidget.open = true;
|
||||
}
|
||||
|
||||
function createNewFaq() {
|
||||
newQuestion = {
|
||||
title: '',
|
||||
@@ -60,34 +73,6 @@
|
||||
$landingPageSettings.faq.questions = filteredFaq;
|
||||
}
|
||||
|
||||
const uploadImage = async (image: File) => {
|
||||
if (image) {
|
||||
const filename = `landingpage/${Date.now()}` + image.name;
|
||||
const { data } = await supabase.storage.from('avatars').upload(filename, image, {
|
||||
cacheControl: '3600',
|
||||
upsert: false
|
||||
});
|
||||
|
||||
if (data) {
|
||||
const { data: response } = await supabase.storage.from('avatars').getPublicUrl(filename);
|
||||
|
||||
$landingPageSettings.aboutUs.imageUrl = response.publicUrl;
|
||||
uploadingImage = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const onFileSelected = (image: File) => {
|
||||
uploadingImage = true;
|
||||
let reader = new FileReader();
|
||||
reader.readAsDataURL(image);
|
||||
reader.onload = (e) => {
|
||||
imageBuffer = image;
|
||||
|
||||
uploadImage(image);
|
||||
};
|
||||
};
|
||||
|
||||
const checkPrefix = (inputValue: string) => {
|
||||
if (!inputValue) return;
|
||||
|
||||
@@ -98,6 +83,7 @@
|
||||
}
|
||||
return inputValue;
|
||||
};
|
||||
|
||||
async function handleSave() {
|
||||
isSaving = true;
|
||||
$landingPageSettings.footer.twitter = checkPrefix($landingPageSettings.footer.twitter) || '';
|
||||
@@ -122,11 +108,18 @@
|
||||
|
||||
function setDefault(landingpage: OrgLandingPageJson) {
|
||||
if (landingpage && Object.keys(landingpage).length) {
|
||||
$landingPageSettings = landingpage;
|
||||
// Added new key, support backward compatibility
|
||||
if (!landingpage?.header?.banner) {
|
||||
landingpage.header.banner = $landingPageSettings.header.banner;
|
||||
}
|
||||
|
||||
$landingPageSettings = {
|
||||
...landingpage
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
$: setDefault($currentOrg?.landingpage);
|
||||
$: setDefault($currentOrg?.landingpage as OrgLandingPageJson);
|
||||
</script>
|
||||
|
||||
<Grid class="border-c rounded border-gray-200 w-full mt-5 relative">
|
||||
@@ -179,18 +172,48 @@
|
||||
<span slot="labelB" style="color: gray">Redirect</span>
|
||||
</Toggle>
|
||||
</div>
|
||||
<SectionTitle>Video</SectionTitle>
|
||||
<div class="gap-2 mt-3 mb-5">
|
||||
<TextField
|
||||
label="Link"
|
||||
placeholder="Write your video link here"
|
||||
bind:value={$landingPageSettings.header.video.link}
|
||||
|
||||
<div />
|
||||
<RadioButtonGroup
|
||||
legendText="Banner Type"
|
||||
bind:selected={$landingPageSettings.header.banner.type}
|
||||
class="mt-10 mb-5"
|
||||
>
|
||||
{#each banner as item}
|
||||
<RadioButton value={item.value} labelText={item.label} />
|
||||
{/each}
|
||||
</RadioButtonGroup>
|
||||
{#if $landingPageSettings.header.banner.type === 'video'}
|
||||
<div class="gap-2 mt-3 mb-5">
|
||||
<TextField
|
||||
label="Link"
|
||||
placeholder="Write your video link here"
|
||||
bind:value={$landingPageSettings.header.banner.video}
|
||||
/>
|
||||
</div>
|
||||
{:else}
|
||||
<PrimaryButton
|
||||
variant={VARIANTS.OUTLINED}
|
||||
label="Select Image"
|
||||
className="mt-3"
|
||||
onClick={() => widgetControl('banner')}
|
||||
/>
|
||||
<Toggle bind:toggled={$landingPageSettings.header.video.show} size="sm">
|
||||
<span slot="labelA" style="color: gray">Hide Video</span>
|
||||
<span slot="labelB" style="color: gray">Show Video</span>
|
||||
</Toggle>
|
||||
</div>
|
||||
{/if}
|
||||
{#if $landingPageSettings.header.banner.image && $landingPageSettings.header.banner.type === 'image'}
|
||||
<img
|
||||
alt="bannerImage"
|
||||
src={$landingPageSettings.header.banner.image}
|
||||
class="mt-2 rounded-md w-full"
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<Toggle bind:toggled={$landingPageSettings.header.banner.show} size="sm">
|
||||
<span slot="labelA" style="color: gray">Hide banner</span>
|
||||
<span slot="labelB" style="color: gray">Show banner</span>
|
||||
</Toggle>
|
||||
{#if $handleOpenWidget.open && widgetKey === 'banner'}
|
||||
<UploadWidget bind:imageURL={$landingPageSettings.header.banner.image} />
|
||||
{/if}
|
||||
</Column>
|
||||
</Row>
|
||||
|
||||
@@ -220,14 +243,12 @@
|
||||
/>
|
||||
|
||||
<div>
|
||||
<FileUploader
|
||||
status={uploadingImage ? 'uploading' : 'complete'}
|
||||
buttonLabel="Select file"
|
||||
labelTitle="Upload an image"
|
||||
class="flex-col items-start gap-2 w-full"
|
||||
accept={['.jpg', '.jpeg', '.png']}
|
||||
bind:files
|
||||
on:change={(file) => onFileSelected(file?.detail?.[0])}
|
||||
<p class="font-bold">Upload an image</p>
|
||||
<PrimaryButton
|
||||
variant={VARIANTS.OUTLINED}
|
||||
label="Select Image"
|
||||
className="mt-3"
|
||||
onClick={() => widgetControl('about-us')}
|
||||
/>
|
||||
{#if $landingPageSettings.aboutUs.imageUrl}
|
||||
<img
|
||||
@@ -236,6 +257,9 @@
|
||||
class="mt-2 rounded-md w-full"
|
||||
/>
|
||||
{/if}
|
||||
{#if $handleOpenWidget.open && widgetKey === 'about-us'}
|
||||
<UploadWidget bind:imageURL={$landingPageSettings.aboutUs.imageUrl} />
|
||||
{/if}
|
||||
</div>
|
||||
</Column>
|
||||
</Row>
|
||||
|
||||
@@ -11,8 +11,10 @@ export interface OrgLandingPageJson {
|
||||
link: string;
|
||||
redirect: boolean;
|
||||
};
|
||||
video: {
|
||||
link: string;
|
||||
banner: {
|
||||
video: string;
|
||||
image: string;
|
||||
type: string;
|
||||
show: boolean;
|
||||
};
|
||||
show: boolean;
|
||||
@@ -72,9 +74,11 @@ export let landingPageSettings: Writable<OrgLandingPageJson> = writable({
|
||||
link: '#contact',
|
||||
redirect: false
|
||||
},
|
||||
video: {
|
||||
show: true,
|
||||
link: 'https://www.youtube.com/watch?v=qqAYW7uxErI'
|
||||
banner: {
|
||||
video: 'https://www.youtube.com/watch?v=qqAYW7uxErI',
|
||||
image: '',
|
||||
type: 'video',
|
||||
show: true
|
||||
},
|
||||
show: true
|
||||
},
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import TextChip from '$lib/components/Chip/Text.svelte';
|
||||
|
||||
export let tabs = [];
|
||||
export let currentTab;
|
||||
export let onChange;
|
||||
interface Tab {
|
||||
icon?: any;
|
||||
label: string;
|
||||
value: string;
|
||||
badgeValue?: number;
|
||||
}
|
||||
export let tabs: Tab[] = [];
|
||||
export let currentTab: string;
|
||||
export let onChange = (v: string) => () => {};
|
||||
</script>
|
||||
|
||||
<div class="w-full flex flex-col">
|
||||
@@ -40,7 +46,7 @@
|
||||
{tab.label}
|
||||
{#if typeof tab.badgeValue === 'number'}
|
||||
<TextChip
|
||||
value={tab.badgeValue}
|
||||
value={`${tab.badgeValue}`}
|
||||
size="sm"
|
||||
shape="rounded-full"
|
||||
className="bg-gray-300 dark:text-black text-xs absolute right-0 px-2"
|
||||
|
||||
@@ -1,91 +1,69 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import Tabs from '$lib/components/Tabs/index.svelte';
|
||||
import { course } from '$lib/components/Course/store';
|
||||
import { getSupabase } from '$lib/utils/functions/supabase';
|
||||
import TabContent from '$lib/components/TabContent/index.svelte';
|
||||
import { updateCourse } from '$lib/utils/services/courses';
|
||||
import { snackbar } from '../Snackbar/store';
|
||||
import { isObject } from '$lib/utils/functions/isObject';
|
||||
import Modal from '$lib/components/Modal/index.svelte';
|
||||
import { handleOpenWidget } from '$lib/components/CourseLandingPage/store';
|
||||
import { settings } from '../Course/components/Settings/store';
|
||||
import { queryUnsplash } from './utils';
|
||||
|
||||
export let selectedImgUrl = '';
|
||||
export let imageURL = '';
|
||||
|
||||
let tabs = [
|
||||
const supabase = getSupabase();
|
||||
const tabs = [
|
||||
{ label: 'Unsplash', value: 'unsplash' },
|
||||
{ label: 'Upload', value: 'upload' }
|
||||
];
|
||||
|
||||
let currentTab = tabs[0].value;
|
||||
let searchQuery = '';
|
||||
let unsplashImages = [];
|
||||
let avatar;
|
||||
let fileInput;
|
||||
let unsplashImages: {
|
||||
id: string | number;
|
||||
urls: {
|
||||
regular: string;
|
||||
};
|
||||
alt_description: string;
|
||||
}[] = [];
|
||||
let fileInput: HTMLInputElement;
|
||||
let imagebuffer;
|
||||
|
||||
const supabase = getSupabase();
|
||||
const onChange = (tabValue) => {
|
||||
currentTab = tabValue;
|
||||
};
|
||||
const onChange = (tabValue: string) => () => (currentTab = tabValue);
|
||||
|
||||
async function handleImageClick(imageUrl) {
|
||||
selectedImgUrl = imageUrl;
|
||||
uploadImage(selectedImgUrl);
|
||||
async function handleImageClick(img: string) {
|
||||
imageURL = img;
|
||||
$handleOpenWidget.open = false;
|
||||
}
|
||||
|
||||
const onFileSelected = () => {
|
||||
const image = fileInput.files[0];
|
||||
if (image) {
|
||||
const file = fileInput?.files?.[0];
|
||||
if (file) {
|
||||
let reader = new FileReader();
|
||||
reader.readAsDataURL(image);
|
||||
reader.readAsDataURL(file);
|
||||
reader.onload = (e) => {
|
||||
imagebuffer = image;
|
||||
uploadImage(image);
|
||||
imagebuffer = file;
|
||||
uploadImage(file);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const uploadImage = async (image) => {
|
||||
if (image) {
|
||||
if (typeof image === 'string') {
|
||||
$settings.image = image;
|
||||
} else if (image instanceof File) {
|
||||
const filename = `bannerimage/${Date.now()}` + image.name;
|
||||
const { data } = await supabase.storage.from('avatars').upload(filename, image, {
|
||||
cacheControl: '3600',
|
||||
upsert: false
|
||||
});
|
||||
|
||||
if (data) {
|
||||
const { data: response } = await supabase.storage.from('avatars').getPublicUrl(filename);
|
||||
|
||||
$settings.image = response.publicUrl;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const { image } = $settings;
|
||||
await updateCourse($course.id, avatar, {
|
||||
logo: image,
|
||||
|
||||
metadata: {
|
||||
...(isObject($course.metadata) ? $course.metadata : {})
|
||||
}
|
||||
});
|
||||
|
||||
$course.logo = image;
|
||||
$course.metadata = {
|
||||
...(isObject($course.metadata) ? $course.metadata : {})
|
||||
};
|
||||
snackbar.success('Saved successfully');
|
||||
$handleOpenWidget.open = false;
|
||||
} catch (error) {
|
||||
snackbar.error();
|
||||
console.log(error);
|
||||
}
|
||||
const uploadImage = async (image: File) => {
|
||||
if (!image) {
|
||||
return;
|
||||
}
|
||||
const filename = `uploadwidget/${Date.now()}` + image.name;
|
||||
const { data } = await supabase.storage.from('avatars').upload(filename, image, {
|
||||
cacheControl: '3600',
|
||||
upsert: false
|
||||
});
|
||||
|
||||
if (data) {
|
||||
const { data: response } = await supabase.storage.from('avatars').getPublicUrl(filename);
|
||||
imageURL = response.publicUrl;
|
||||
}
|
||||
|
||||
snackbar.success(`Complete :)`);
|
||||
$handleOpenWidget.open = false;
|
||||
};
|
||||
|
||||
function handleUpload() {
|
||||
@@ -96,6 +74,7 @@
|
||||
try {
|
||||
unsplashImages = await queryUnsplash(searchQuery || 'rocks');
|
||||
} catch (error) {
|
||||
snackbar.error('Error fetching images from Unsplash');
|
||||
console.error('Error fetching images from Unsplash:', error);
|
||||
}
|
||||
}
|
||||
@@ -153,12 +132,13 @@
|
||||
<div class="flex flex-row items-center flex-wrap gap-2 py-4 px-[10px] max-h-[300px]">
|
||||
{#each unsplashImages as unsplashImages (unsplashImages.id)}
|
||||
<div class="w-[190px] h-[130px] overflow-hidden relative">
|
||||
<img
|
||||
src={unsplashImages.urls.regular}
|
||||
alt={unsplashImages.alt_description}
|
||||
class="w-full h-full object-cover rounded-md hover:opacity-80 cursor-pointer"
|
||||
on:click={() => handleImageClick(unsplashImages.urls.regular)}
|
||||
/>
|
||||
<button on:click={() => handleImageClick(unsplashImages.urls.regular)}>
|
||||
<img
|
||||
src={unsplashImages.urls.regular}
|
||||
alt={unsplashImages.alt_description}
|
||||
class="w-full h-full object-cover rounded-md hover:opacity-80 cursor-pointer"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -8,9 +8,10 @@
|
||||
"link": "#contact",
|
||||
"redirect": false
|
||||
},
|
||||
"video": {
|
||||
"show": false,
|
||||
"link": "https://youtube.com/sosf24lsfgs"
|
||||
"banner": {
|
||||
"video": "https://youtube.com/sosf24lsfgs",
|
||||
"image": "",
|
||||
"show": false
|
||||
},
|
||||
"show": true
|
||||
},
|
||||
@@ -64,4 +65,4 @@
|
||||
"instagram": "#",
|
||||
"linkedin": "#"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,9 @@ export interface CurrentOrg {
|
||||
avatar_url: string;
|
||||
memberId: string;
|
||||
role_id: string;
|
||||
landingpage: {};
|
||||
landingpage: {
|
||||
[key: string]: any;
|
||||
};
|
||||
theme: string;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user