Skip to content

Commit

Permalink
✨ Add share component (#5727)
Browse files Browse the repository at this point in the history
Co-authored-by: Francisco Aranda <[email protected]>
Co-authored-by: Paco Aranda <[email protected]>
Co-authored-by: Leire <[email protected]>
Co-authored-by: José Francisco Calvo <[email protected]>
  • Loading branch information
5 people authored Dec 18, 2024
1 parent d6f823b commit 3643cf3
Show file tree
Hide file tree
Showing 31 changed files with 556 additions and 111 deletions.
1 change: 1 addition & 0 deletions argilla-frontend/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ These are the section headers that we use:

### Added

- Add share progress feature ([#5727](https://github.com/argilla-io/argilla/pull/5727))
- Added feature to export datasets from Argilla to Hugging Face hub from the UI ([#5730](https://github.com/argilla-io/argilla/pull/5730))

### Fixed
Expand Down
6 changes: 6 additions & 0 deletions argilla-frontend/components/base/base-button/BaseButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
:target="target"
:rel="newRel"
@click="onClick"
@mouseover="$emit('mouseover')"
@mouseleave="$emit('mouseleave')"
>
<slot />
</a>
Expand All @@ -36,6 +38,8 @@
:loading="loading"
:disabled="disabled"
@click="onClick"
@mouseover="$emit('mouseover')"
@mouseleave="$emit('mouseleave')"
>
<slot />
</nuxt-link>
Expand All @@ -48,6 +52,8 @@
:type="type"
:disabled="disabled"
@click="onClick"
@mouseover="$emit('mouseover')"
@mouseleave="$emit('mouseleave')"
>
<BaseSpinner
class="spinner"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,19 @@
v-if="!metrics.hasMetrics"
class="my-progress__status--skeleton"
/>
<StatusCounter
v-else
class="my-progress__status"
:color="RecordStatus.submitted.color"
:name="RecordStatus.submitted.name"
:value="metrics.submitted"
/>
<div v-else class="my-progress__share">
<Share v-if="canSeeShare" />
<StatusCounter
:ghost="true"
:rainbow="shouldShowSubmittedAnimation"
class="my-progress__status"
:color="RecordStatus.submitted.color"
:name="RecordStatus.submitted.name"
:value="metrics.submitted"
/>
</div>
</div>
</template>

<script>
import { RecordStatus } from "~/v1/domain/entities/record/RecordStatus";
import { useAnnotationProgressViewModel } from "./useAnnotationProgressViewModel";
Expand Down Expand Up @@ -71,5 +74,12 @@ $statusCounterMinHeight: 30px;
min-height: $statusCounterMinHeight;
}
}
&__share {
width: 100%;
display: flex;
align-items: center;
justify-content: end;
gap: $base-space;
}
}
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<template>
<div class="share" @click.stop="copyOnClipboard">
<BaseActionTooltip :tooltip="$t('copiedToClipboard')">
<BaseButton
class="share__button"
:title="$t('button.tooltip.copyToClipboard')"
@mouseover="openDialog"
@mouseleave="closeDialog"
>
<svgicon class="share__icon" name="link" width="14" height="14" />
{{ $t("share") }}
</BaseButton>
</BaseActionTooltip>
<transition name="fade" appear>
<dialog
v-if="isDialogOpen"
class="share__dialog"
v-click-outside="closeDialog"
>
<div class="share__dialog--container">
<BaseSpinner v-if="!sharingImage.loaded" :size="20" />
<img v-else :src="sharingImage.src" />
</div>
</dialog>
</transition>
</div>
</template>
<script>
import { useShareViewModel } from "./useShareViewModel";
export default {
setup() {
return useShareViewModel();
},
};
</script>

<style lang="scss" scoped>
$bullet-size: 8px;
.share {
z-index: 2;
margin-left: auto;
margin-right: 0;
&__dialog {
position: absolute;
right: 1em;
left: auto;
width: auto;
height: 204px;
min-width: 360px;
max-width: 360px;
bottom: calc(100% + $base-space + 2px);
display: block;
padding: $base-space * 2;
border: 1px solid var(--bg-opacity-10);
border-radius: $border-radius-m;
box-shadow: $shadow;
z-index: 2;
&--container {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
}
&__button {
@include font-size(12px);
height: 24px;
padding: $base-space;
background: var(--bg-opacity-3);
border-radius: $border-radius;
}
&__icon {
padding: 0;
flex-shrink: 0;
}
}
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { onBeforeMount, ref } from "vue";
import { useUser } from "~/v1/infrastructure/services";
import { useClipboard } from "~/v1/infrastructure/services/useClipboard";
import { useDataset } from "~/v1/infrastructure/storage/DatasetStorage";
import { useMetrics } from "~/v1/infrastructure/storage/MetricsStorage";
import { useTeamProgress } from "~/v1/infrastructure/storage/TeamProgressStorage";

export const useShareViewModel = () => {
const { copy } = useClipboard();
const { user } = useUser();
const { state: metrics } = useMetrics();
const { state: dataset } = useDataset();
const { state: progress } = useTeamProgress();

const isDialogOpen = ref(false);
const sharingImage = ref<{
src: string;
loaded: boolean;
}>({
src: "",
loaded: false,
});

const copyOnClipboard = () => {
closeDialog();

const url = new URL(`${window.location.origin}/share-your-progress`);
const params = new URLSearchParams("");
params.set("user_name", user.value.userName);
params.set("records_submitted", metrics.submitted.toString());
params.set("team_progress", progress.percentage.completed.toString());
params.set("dataset_name", dataset.name);
params.set("dataset_id", dataset.id);

url.search = params.toString();

const textToCopy = `I've just contributed ${
metrics.submitted
} examples to this dataset:
${url.toString()}`;

copy(textToCopy);
};

const createImageLink = () => {
const url = new URL("https://argilla.imglab-cdn.net/dibt/dibt_v2.png");
const params = new URLSearchParams(url.search);
params.set("width", "1200");
params.set("text-width", "700");
params.set("text-height", "590");
params.set("text-padding", "60");
params.set("text-color", "39,71,111");
params.set("text-x", "460");
params.set("text-y", "40");

params.set(
"text",
`<span size="9pt" weight="bold">@${user.value.userName}</span>
I've just contributed <span weight="bold">${metrics.submitted}</span> examples to this dataset:
<span size="9pt" weight="bold">${dataset.name}</span>
<span size="8pt">Team progress</span>
<span weight="bold">${progress.percentage.completed}%</span>`
);

return `${url.origin}${url.pathname}?${params.toString()}`;
};

const openDialog = () => {
setPreloadedImage();

isDialogOpen.value = true;
};

const closeDialog = () => {
isDialogOpen.value = false;
};

const setPreloadedImage = () => {
sharingImage.value.loaded = false;

const image = createImageLink();

const preFetchImage = new Image();
preFetchImage.src = image;
preFetchImage.onload = () => {
sharingImage.value = {
src: image,
loaded: true,
};
};
};

onBeforeMount(() => {
setPreloadedImage();
});

return {
sharingImage,
isDialogOpen,
openDialog,
closeDialog,
copyOnClipboard,
};
};
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
<template>
<li class="status-counter">
<li class="status-counter" :class="{ rainbow, ghost }">
<span>
<span class="color-bullet" :style="{ backgroundColor: color }"></span>
<label class="status-counter__name" v-text="statusLabel" />
</span>
<span class="status-counter__counter" v-text="value" />
</li>
</template>

<script>
export default {
props: {
Expand All @@ -23,6 +22,14 @@ export default {
type: Number,
required: true,
},
rainbow: {
type: Boolean,
default: false,
},
ghost: {
type: Boolean,
default: false,
},
},
computed: {
statusLabel() {
Expand Down Expand Up @@ -60,4 +67,51 @@ $bullet-size: 8px;
@include font-size(14px);
}
}
.ghost {
background: none;
}
.rainbow {
position: relative;
padding: $base-space;
}
.rainbow::before {
content: "";
position: absolute;
top: -2px;
right: -2px;
bottom: -2px;
left: -2px;
border-radius: $border-radius;
border: solid 2px transparent;
border-image: conic-gradient(
from var(--angle),
#e70000,
#ff8c00,
#ffef00,
#00811f,
#3064a9,
#87189d
)
1;
animation: 2s rotate linear infinite;
filter: blur(1px);
z-index: -1;
mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0);
mask-composite: exclude;
}
@keyframes rotate {
to {
--angle: 360deg;
}
}
@property --angle {
syntax: "<angle>";
initial-value: 0deg;
inherits: false;
}
</style>
Original file line number Diff line number Diff line change
@@ -1,18 +1,35 @@
import { onBeforeMount } from "vue-demi";
import { computed, onBeforeMount, ref } from "vue-demi";
import {
useEvents,
UpdateMetricsEventHandler,
} from "~/v1/infrastructure/events";
import { useRunningEnvironment } from "~/v1/infrastructure/services";
import { useMetrics } from "~/v1/infrastructure/storage/MetricsStorage";

export const useAnnotationProgressViewModel = () => {
const isShareYourProgressEnabled = ref<boolean>(false);

const { state: metrics } = useMetrics();
const { getShareYourProgressEnabled } = useRunningEnvironment();

onBeforeMount(async () => {
isShareYourProgressEnabled.value = await getShareYourProgressEnabled();
});

const canSeeShare = computed(
() => isShareYourProgressEnabled.value && metrics.submitted >= 2
);
const shouldShowSubmittedAnimation = computed(
() => canSeeShare.value && metrics.submitted % 10 === 0
);

onBeforeMount(() => {
useEvents(UpdateMetricsEventHandler);
});

return {
metrics,
canSeeShare,
shouldShowSubmittedAnimation,
};
};
3 changes: 3 additions & 0 deletions argilla-frontend/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ const config: NuxtConfig = {
"/api/": {
target: BASE_URL,
},
"/share-your-progress": {
target: BASE_URL,
},
},
// Build Configuration (https://go.nuxtjs.dev/config-build)
build: {
Expand Down
Loading

0 comments on commit 3643cf3

Please sign in to comment.