Skip to content
This repository has been archived by the owner on Dec 2, 2024. It is now read-only.

feat: Elfsight improvements #535

Merged
merged 2 commits into from
Nov 8, 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
2 changes: 1 addition & 1 deletion domains/grid/components/AddWidget.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const WIDGET_COMPONENTS: Record<string, string> = {
[GRID_WIDGET_TYPE.enum.SOUNDCLOUD]: 'Basic',
[GRID_WIDGET_TYPE.enum.WARPCAST]: 'Basic',
[GRID_WIDGET_TYPE.enum.YOUTUBE]: 'Basic',
[GRID_WIDGET_TYPE.enum.ELFSIGHT]: 'Basic',
[GRID_WIDGET_TYPE.enum.ELFSIGHT]: 'Elfsight',
}

const loadComponent = (type?: string): Component | undefined => {
Expand Down
172 changes: 172 additions & 0 deletions domains/grid/components/AddWidgetElfsight.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
<script setup lang="ts">
type Props = {
type: GridWidgetType
id?: string
properties?: ElfsightWidgetProperties
width?: number
height?: number
}

const props = defineProps<Props>()
const { formatMessage } = useIntl()
const { closeModal, showModal } = useModal()
const { addGridWidget, updateGridWidget, getGridById } = useGrid()
const { tempGrid, selectedGridId } = storeToRefs(useGridStore())
const isEdit = computed(() => !!props.id)
const widgetType = computed(() => props.type)

const schemaMap = WIDGET_SCHEMA_MAP[widgetType.value]
const {
inputValues,
canSubmit,
getFieldErrorMessage,
handleFieldChange,
handleFormErrors,
} = useForm(schemaMap?.input, {
input: props.properties?.id,
})
const isInstructionsVisible = ref(false)

const handleSave = async () => {
if (!canSubmit.value) {
return
}

try {
const inputParse = await schemaMap?.input?.safeParseAsync(inputValues.value)
const properties = await schemaMap?.output?.parseAsync(inputParse?.data)

if (isEdit.value) {
updateGridWidget(props.id, {
properties,
w: props.width,
h: props.height,
})
} else {
const newWidget: GridWidgetWithoutCords = createWidgetObject({
type: inputParse?.data?.widgetType, // widget type is not based on selection but on the parsing result
properties,
w: props.width,
h: props.height,
})

addGridWidget(
newWidget,
getGridById(tempGrid.value, selectedGridId.value)
)
}

handleCancel()
} catch (error: unknown) {
handleFormErrors(error)
}
}

const handleCancel = () => {
closeModal()
}

const handleBackToSelection = () => {
showModal<Partial<GridWidget>>({
template: 'AddGridWidget',
forceOpen: true,
})
}

const widgetInstructions = computed(() => {
return formatMessage(
`add_widget_${widgetType.value.toLowerCase()}_instructions`
)
})

const hasInstructions = computed(() => widgetInstructions.value !== '-')
</script>

<template>
<div class="p-6">
<div class="flex items-center gap-3 pb-4">
<lukso-icon
v-if="!isEdit"
name="arrow-left-sm"
class="relative z-[1] cursor-pointer rounded-full bg-neutral-100 shadow-neutral-above-shadow transition hover:scale-105 hover:shadow-neutral-above-shadow-1xl active:scale-100 active:shadow-neutral-above-shadow"
@click="handleBackToSelection"
></lukso-icon>
<div class="heading-inter-21-semi-bold">
{{
formatMessage(
`${isEdit ? 'edit' : 'add'}_widget_${widgetType.toLowerCase()}_title`
)
}}
</div>
</div>
<div class="paragraph-inter-14-regular pb-6">
{{
formatMessage(
`${isEdit ? 'edit' : 'add'}_widget_${widgetType.toLowerCase()}_description`
)
}}

<!-- Instructions -->
<div v-if="hasInstructions" class="mt-2">
<div class="flex items-center">
<span
v-if="isInstructionsVisible"
class="cursor-pointer text-purple-51 underline hover:text-purple-41"
@click="isInstructionsVisible = !isInstructionsVisible"
>Hide instructions</span
>
<span
v-else
class="cursor-pointer text-purple-51 underline hover:text-purple-41"
@click="isInstructionsVisible = !isInstructionsVisible"
>Show instructions</span
>
<lukso-icon
name="arrow-down-sm"
color="purple-51"
:class="{
'rotate-180 transition': isInstructionsVisible,
}"
></lukso-icon>
</div>
<div
v-if="isInstructionsVisible"
class="mt-4 animate-fade-in whitespace-pre-line font-600 break-word"
>
{{ widgetInstructions }}
</div>
</div>
</div>

<!-- Content -->
<lukso-textarea
is-full-width
autofocus
:placeholder="
formatMessage(
`add_widget_${widgetType.toLowerCase()}_input_placeholder`
)
"
:value="inputValues.input"
:error="getFieldErrorMessage('input')"
@on-input="
(customEvent: CustomEvent) => handleFieldChange(customEvent, 'input')
"
></lukso-textarea>

<!-- Buttons -->
<div class="grid grid-cols-[max-content,auto] pt-6">
<lukso-button variant="text" @click="handleCancel">
{{ formatMessage('add_widget_cancel') }}
</lukso-button>
<lukso-button
:disabled="!canSubmit ? true : undefined"
variant="landing"
is-full-width
@click="handleSave"
>
{{ formatMessage('add_widget_confirm') }}
</lukso-button>
</div>
</div>
</template>
11 changes: 5 additions & 6 deletions domains/grid/components/AddWidgetSelection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,13 @@ const handleSelectWidget = (widgetType: GridWidgetType) => {
variant="light"
:show-delay="SHOW_TOOLTIP_DELAY"
:text="formatMessage('widget_type_elfsight')"
class="hidden"
>
<img
src="/images/elfsight.png"
:alt="formatMessage('widget_type_elfsight')"
class="size-10 cursor-pointer transition hover:scale-105"
<div
class="flex size-10 cursor-pointer items-center justify-center rounded-full bg-neutral-20 transition hover:scale-105"
@click="handleSelectWidget('ELFSIGHT')"
/>
>
<lukso-icon name="logo-elfsight-mono" size="large"></lukso-icon>
</div>
</lukso-tooltip>
</div>
</section>
Expand Down
35 changes: 26 additions & 9 deletions domains/grid/components/GridWidgetElfsight.vue
Original file line number Diff line number Diff line change
@@ -1,19 +1,36 @@
<script setup lang="ts">
import { useScriptTag } from '@vueuse/core'

type Props = {
id: string
}

defineProps<Props>()
useScriptTag('https://static.elfsight.com/platform/platform.js', () => {}, {
async: true,
defer: true,
})
const props = defineProps<Props>()
const embedId = ref('')

watch(
() => props.id,
async () => {
embedId.value = ''
await nextTick()
const script = document.createElement('script')
script.src = 'https://static.elfsight.com/platform/platform.js'
script.async = true
script.defer = true

const existingScript = document.querySelector(`script[src="${script.src}"]`)

if (existingScript) {
existingScript.remove()
}

embedId.value = props.id
document.body.appendChild(script)
},
{ immediate: true, deep: true }
)
</script>

<template>
<div class="relative m-3 overflow-auto">
<div :class="`elfsight-app-${id}`" data-elfsight-app-lazy></div>
<div v-if="embedId" class="relative m-3 overflow-auto">
<div :class="`elfsight-app-${embedId}`" data-elfsight-app-lazy></div>
</div>
</template>
7 changes: 7 additions & 0 deletions domains/grid/components/GridWidgetIframe.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ const reloadIframe = () => {
onResize()
}

watch(
() => props.src,
() => {
reloadIframe()
}
)

useResizeObserver(iframeRef, useDebounceFn(reloadIframe, 100))
</script>

Expand Down
6 changes: 4 additions & 2 deletions domains/grid/schema/elfsightWidgetSchema.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { z } from 'zod'

export const elfsightWidgetSchema = iframeWidgetSchema.extend({})
export const elfsightWidgetSchema = z.object({
id: z.string(),
})

export const elfsightWidgetInputSchema = iframeWidgetSchema
.partial()
Expand All @@ -11,4 +13,4 @@ export const elfsightWidgetInputSchema = iframeWidgetSchema
platformParseTransform(values.input, ctx, GRID_WIDGET_TYPE.enum.ELFSIGHT)
)

export type ElfSightWidgetProperties = z.input<typeof elfsightWidgetSchema>
export type ElfsightWidgetProperties = z.input<typeof elfsightWidgetSchema>
Binary file removed public/images/elfsight.png
Binary file not shown.
6 changes: 6 additions & 0 deletions translations/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
"no_asset_balance": "You don't own this asset.",
"grid_widget_menu_edit": "Edit",
"asset_all_creators_partial": "Not all creators are verified",
"edit_widget_elfsight_title": "Edit Elfsight widget",
"add_widget_confirm": "Save",
"header_install_extension": "Install Extension",
"own_connected_profile_following_empty": "You follow no one",
Expand Down Expand Up @@ -153,6 +154,7 @@
"edit_widget_x_description": "Edit this widget to display any X timeline or post.",
"collection_not_avail_link": "in the settings",
"add_widget_instagram_description": "Allows to embed Instagram post.",
"add_widget_elfsight_input_placeholder": "Add any Elfsight embed code",
"token_asset_type_other": "OTHER",
"profile_tab_tokens": "Tokens",
"modal_mobile_search_placeholder": "Search by title",
Expand All @@ -178,6 +180,7 @@
"shuffle_title": "Profiles",
"token_asset_type_video": "VIDEO",
"beta_warning": "You are on <strong>LUKSO Testnet</strong>. Do not send real LYX to any profiles made on this network!<br /><strong>If you are looking for LUKSO Mainnet, please use the switch in the footer.</strong>",
"edit_widget_elfsight_description": "Use this widget to display Elfsight on your grid.",
"add_widget_iframe_input_placeholder": "URL of the webpage",
"add_widget_text_link_placeholder": "Link URL",
"profile_card_follow_button": "Follow",
Expand Down Expand Up @@ -273,6 +276,7 @@
"token_collection_of": "Owns {count}",
"add_widget_images_description": "Use this widget to display images from the web directly on your grid for visitors to view. Please note that uploading an image from your device is not available.",
"grid_mobile_limitations_message": "some editing features are not available on mobile right now",
"add_widget_elfsight_instructions": "-",
"add_widget_text_title_placeholder": "Please add a title",
"data_provider_rpc_description": "Loads data directly from the blockchain using an RPC provider. If a custom RPC provider (This feature will be added later) is used the read data can not be manipulated by us. \n\nWill result in slower loading times during the loading of assets and some app features might be limited.",
"move_widget_description": "Please select to which Grid you want to move this widget.",
Expand All @@ -292,6 +296,7 @@
"token_details_buy_lyx": "Buy LYX",
"footer_terms_text": "Terms & Conditions",
"followed_by_text": "Followed by {names} {othersCount, plural,\n =0 {you follow}\n =1 {and 1 other you follow}\n other {and # others you follow}\n }",
"add_widget_elfsight_description": "Use this widget to display Elfsight on your grid.",
"assets_empty_state_description": "To find out how to create your own assets such as Tokens and NFT’s on <strong>LUKSO</strong> head over to our <a href=\"https://docs.lukso.tech/guides/digital-assets/create-lsp7-digital-asset/\" target=\"_blank\" class=\"text-purple-51 hover:text-purple-41 underline\"><strong>documentation</strong></a>. ",
"connect_or_install_button_coming_soon": "Coming soon...",
"modal_delete_widget_confirm": "Delete",
Expand Down Expand Up @@ -323,6 +328,7 @@
"missing_asset_label_missing": "Missing",
"add_widget_images_placeholder": "URL of the image",
"buy_lyx_card_buy_button": "Buy LYX",
"add_widget_elfsight_title": "Add Elfsight widget",
"edit_widget_text_description": "Edit this widget to display and customize any text on your grid.",
"error_unknown_standard": "Couldn't detect standard for this asset.",
"settings_data_provider_title": "Data loading mode",
Expand Down
Loading