i18n: add missing __() calls to complete French translation
This commit is contained in:
@@ -157,7 +157,7 @@
|
|||||||
v-model="showHelpModal"
|
v-model="showHelpModal"
|
||||||
v-model:articles="articles"
|
v-model:articles="articles"
|
||||||
appName="learning"
|
appName="learning"
|
||||||
title="Frappe Learning"
|
:title="__('Frappe Learning')"
|
||||||
:logo="LMSLogo"
|
:logo="LMSLogo"
|
||||||
:afterSkip="(step) => capture('onboarding_step_skipped_' + step)"
|
:afterSkip="(step) => capture('onboarding_step_skipped_' + step)"
|
||||||
:afterSkipAll="() => capture('onboarding_steps_skipped')"
|
:afterSkipAll="() => capture('onboarding_steps_skipped')"
|
||||||
@@ -303,7 +303,7 @@ const unreadNotifications = createResource({
|
|||||||
const addNotifications = () => {
|
const addNotifications = () => {
|
||||||
if (user) {
|
if (user) {
|
||||||
sidebarLinks.value.push({
|
sidebarLinks.value.push({
|
||||||
label: 'Notifications',
|
label: __('Notifications'),
|
||||||
icon: 'Bell',
|
icon: 'Bell',
|
||||||
to: 'Notifications',
|
to: 'Notifications',
|
||||||
activeFor: ['Notifications'],
|
activeFor: ['Notifications'],
|
||||||
@@ -315,7 +315,7 @@ const addNotifications = () => {
|
|||||||
const addQuizzes = () => {
|
const addQuizzes = () => {
|
||||||
if (isInstructor.value || isModerator.value) {
|
if (isInstructor.value || isModerator.value) {
|
||||||
sidebarLinks.value.splice(4, 0, {
|
sidebarLinks.value.splice(4, 0, {
|
||||||
label: 'Quizzes',
|
label: __('Quizzes'),
|
||||||
icon: 'CircleHelp',
|
icon: 'CircleHelp',
|
||||||
to: 'Quizzes',
|
to: 'Quizzes',
|
||||||
activeFor: [
|
activeFor: [
|
||||||
@@ -331,7 +331,7 @@ const addQuizzes = () => {
|
|||||||
const addAssignments = () => {
|
const addAssignments = () => {
|
||||||
if (isInstructor.value || isModerator.value) {
|
if (isInstructor.value || isModerator.value) {
|
||||||
sidebarLinks.value.splice(5, 0, {
|
sidebarLinks.value.splice(5, 0, {
|
||||||
label: 'Assignments',
|
label: __('Assignments'),
|
||||||
icon: 'Pencil',
|
icon: 'Pencil',
|
||||||
to: 'Assignments',
|
to: 'Assignments',
|
||||||
activeFor: [
|
activeFor: [
|
||||||
@@ -347,7 +347,7 @@ const addAssignments = () => {
|
|||||||
const addProgrammingExercises = () => {
|
const addProgrammingExercises = () => {
|
||||||
if (isInstructor.value || isModerator.value) {
|
if (isInstructor.value || isModerator.value) {
|
||||||
sidebarLinks.value.splice(3, 0, {
|
sidebarLinks.value.splice(3, 0, {
|
||||||
label: 'Programming Exercises',
|
label: __('Programming Exercises'),
|
||||||
icon: 'Code',
|
icon: 'Code',
|
||||||
to: 'ProgrammingExercises',
|
to: 'ProgrammingExercises',
|
||||||
activeFor: [
|
activeFor: [
|
||||||
@@ -383,7 +383,7 @@ const addPrograms = () => {
|
|||||||
|
|
||||||
if (canAddProgram) {
|
if (canAddProgram) {
|
||||||
sidebarLinks.value.splice(index, 0, {
|
sidebarLinks.value.splice(index, 0, {
|
||||||
label: 'Programs',
|
label: __('Programs'),
|
||||||
icon: 'Route',
|
icon: 'Route',
|
||||||
to: 'Programs',
|
to: 'Programs',
|
||||||
activeFor: activeFor,
|
activeFor: activeFor,
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
emptyStateText: {
|
emptyStateText: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'Start a discussion',
|
default: __('Start a discussion'),
|
||||||
},
|
},
|
||||||
singleThread: {
|
singleThread: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
<div class="flex flex-col items-center justify-center mt-60">
|
<div class="flex flex-col items-center justify-center mt-60">
|
||||||
<GraduationCap class="size-10 mx-auto stroke-1 text-ink-gray-5" />
|
<GraduationCap class="size-10 mx-auto stroke-1 text-ink-gray-5" />
|
||||||
<div class="text-lg font-semibold text-ink-gray-7 mb-2.5">
|
<div class="text-lg font-semibold text-ink-gray-7 mb-2.5">
|
||||||
|
|
||||||
{{ __('No {0}').format(props.type) }}
|
{{ __('No {0}').format(props.type) }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
|||||||
70
frontend/src/overrides/Onboarding/GettingStartedBanner.vue
Normal file
70
frontend/src/overrides/Onboarding/GettingStartedBanner.vue
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
v-if="!isSidebarCollapsed"
|
||||||
|
class="flex flex-col gap-3 shadow-sm rounded-lg py-2.5 px-3 bg-surface-modal text-base"
|
||||||
|
>
|
||||||
|
<div v-if="stepsCompleted != totalSteps" class="inline-flex text-ink-gray-9 gap-2">
|
||||||
|
<StepsIcon class="h-4 my-0.5 shrink-0" />
|
||||||
|
<div class="flex flex-col text-p-sm gap-0.5">
|
||||||
|
<div class="font-medium">
|
||||||
|
{{ __('Getting started') }}
|
||||||
|
</div>
|
||||||
|
<div class="text-ink-gray-7">
|
||||||
|
{{ __('{0}/{1} steps').format(stepsCompleted, totalSteps) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else class="flex flex-col gap-1">
|
||||||
|
<div class="flex items-center justify-between gap-1">
|
||||||
|
<div class="flex items-center gap-2 shrink-0">
|
||||||
|
<StepsIcon class="h-4 my-0.5" />
|
||||||
|
<div class="text-ink-gray-9 font-medium">
|
||||||
|
{{ __('You are all set') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<FeatherIcon
|
||||||
|
name="x"
|
||||||
|
class="h-4 cursor-pointer"
|
||||||
|
@click="() => { showHelpCenter = true; isOnboardingStepsCompleted = true }"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="text-p-sm text-ink-gray-7">
|
||||||
|
{{ __('All steps are completed successfully') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
v-if="stepsCompleted != totalSteps"
|
||||||
|
:label="stepsCompleted == 0 ? __('Start now') : __('Continue')"
|
||||||
|
theme="blue"
|
||||||
|
@click="openOnboarding"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<FeatherIcon name="chevrons-right" class="size-4" />
|
||||||
|
</template>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<Button v-else-if="stepsCompleted != totalSteps" @click="openOnboarding">
|
||||||
|
<StepsIcon class="h-4 my-0.5 shrink-0" />
|
||||||
|
</Button>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import StepsIcon from 'frappe-ui/frappe/Icons/StepsIcon.vue'
|
||||||
|
import Button from 'frappe-ui/src/components/Button/Button.vue'
|
||||||
|
import FeatherIcon from 'frappe-ui/src/components/FeatherIcon.vue'
|
||||||
|
import { useOnboarding } from 'frappe-ui/frappe/Onboarding/onboarding'
|
||||||
|
import { showHelpCenter } from 'frappe-ui/frappe/HelpCenter/helpCenter'
|
||||||
|
import { showHelpModal, minimize } from 'frappe-ui/frappe/Help/help'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
isSidebarCollapsed: { type: Boolean, default: false },
|
||||||
|
appName: { type: String, default: 'frappecrm' },
|
||||||
|
})
|
||||||
|
|
||||||
|
const { stepsCompleted, totalSteps, isOnboardingStepsCompleted } = useOnboarding(props.appName)
|
||||||
|
|
||||||
|
const openOnboarding = () => {
|
||||||
|
minimize.value = false
|
||||||
|
showHelpModal.value = true
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
112
frontend/src/overrides/Onboarding/OnboardingSteps.vue
Normal file
112
frontend/src/overrides/Onboarding/OnboardingSteps.vue
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
<template>
|
||||||
|
<div class="flex flex-col justify-center items-center gap-1 mt-4 mb-7">
|
||||||
|
<component :is="logo" class="size-10 shrink-0 rounded mb-4" />
|
||||||
|
<div class="text-base font-medium">
|
||||||
|
{{ __('Welcome to {0}').format(title) }}
|
||||||
|
</div>
|
||||||
|
<div class="text-p-base font-normal">
|
||||||
|
{{ __('{0}/{1} steps completed').format(stepsCompleted, totalSteps) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col gap-2.5 overflow-hidden">
|
||||||
|
<div class="flex justify-between items-center py-0.5">
|
||||||
|
<Badge
|
||||||
|
:label="__('{0}% completed').format(completedPercentage)"
|
||||||
|
:theme="completedPercentage == 100 ? 'green' : 'orange'"
|
||||||
|
size="lg"
|
||||||
|
/>
|
||||||
|
<div class="flex">
|
||||||
|
<Button
|
||||||
|
v-if="completedPercentage != 0"
|
||||||
|
variant="ghost"
|
||||||
|
:label="__('Reset all')"
|
||||||
|
@click="() => resetAll(afterResetAll)"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
v-if="completedPercentage != 100"
|
||||||
|
variant="ghost"
|
||||||
|
:label="__('Skip all')"
|
||||||
|
@click="() => skipAll(afterSkipAll)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col gap-1.5 overflow-y-auto">
|
||||||
|
<div
|
||||||
|
v-for="step in steps"
|
||||||
|
:key="step.title"
|
||||||
|
class="group w-full flex gap-2 justify-between items-center hover:bg-surface-gray-1 rounded px-2 py-1.5 cursor-pointer"
|
||||||
|
@click.stop="() => !step.completed && !isDependent(step) && step.onClick()"
|
||||||
|
>
|
||||||
|
<component :is="isDependent(step) ? Tooltip : 'div'" :text="dependsOnTooltip(step)">
|
||||||
|
<div
|
||||||
|
class="flex gap-2 items-center"
|
||||||
|
:class="[
|
||||||
|
step.completed
|
||||||
|
? 'text-ink-gray-5'
|
||||||
|
: isDependent(step)
|
||||||
|
? 'text-ink-gray-4'
|
||||||
|
: 'text-ink-gray-8',
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<component :is="step.icon" class="h-4" />
|
||||||
|
<div class="text-base" :class="{ 'line-through': step.completed }">
|
||||||
|
{{ step.title }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</component>
|
||||||
|
<Button
|
||||||
|
v-if="!step.completed && !isDependent(step)"
|
||||||
|
:label="__('Skip')"
|
||||||
|
class="!h-4 text-xs !text-ink-gray-6 hidden group-hover:flex"
|
||||||
|
@click="() => skip(step.name, afterSkip)"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
v-else-if="!isDependent(step)"
|
||||||
|
:label="__('Reset')"
|
||||||
|
class="!h-4 text-xs !text-ink-gray-6 hidden group-hover:flex"
|
||||||
|
@click.stop="() => reset(step.name, afterReset)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { useOnboarding } from 'frappe-ui/frappe/Onboarding/onboarding'
|
||||||
|
import Tooltip from 'frappe-ui/src/components/Tooltip/Tooltip.vue'
|
||||||
|
import Button from 'frappe-ui/src/components/Button/Button.vue'
|
||||||
|
import Badge from 'frappe-ui/src/components/Badge/Badge.vue'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
appName: { type: String, default: 'frappecrm' },
|
||||||
|
title: { type: String, default: 'Frappe CRM' },
|
||||||
|
logo: { type: Object, required: true },
|
||||||
|
afterSkip: { type: Function, default: () => {} },
|
||||||
|
afterSkipAll: { type: Function, default: () => {} },
|
||||||
|
afterReset: { type: Function, default: () => {} },
|
||||||
|
afterResetAll: { type: Function, default: () => {} },
|
||||||
|
})
|
||||||
|
|
||||||
|
function isDependent(step) {
|
||||||
|
if (step.dependsOn && !step.completed) {
|
||||||
|
const dependsOnStep = steps.find((s) => s.name === step.dependsOn)
|
||||||
|
if (dependsOnStep && !dependsOnStep.completed) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
function dependsOnTooltip(step) {
|
||||||
|
if (step.dependsOn && !step.completed) {
|
||||||
|
const dependsOnStep = steps.find((s) => s.name === step.dependsOn)
|
||||||
|
if (dependsOnStep && !dependsOnStep.completed) {
|
||||||
|
return `You need to complete "${dependsOnStep.title}" first.`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
const { steps, stepsCompleted, totalSteps, completedPercentage, skip, skipAll, reset, resetAll } =
|
||||||
|
useOnboarding(props.appName)
|
||||||
|
</script>
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
</ListView>
|
</ListView>
|
||||||
<EmptyState v-else type="Assignments" />
|
<EmptyState v-else :type="__('Assignments').toLowerCase()" />
|
||||||
<div
|
<div
|
||||||
v-if="assignments.data && assignments.hasNextPage"
|
v-if="assignments.data && assignments.hasNextPage"
|
||||||
class="flex justify-center my-5"
|
class="flex justify-center my-5"
|
||||||
@@ -198,7 +198,7 @@ const assignmentTypes = computed(() => {
|
|||||||
|
|
||||||
const breadcrumbs = computed(() => [
|
const breadcrumbs = computed(() => [
|
||||||
{
|
{
|
||||||
label: 'Assignments',
|
label: __('Assignments'),
|
||||||
route: { name: 'Assignments' },
|
route: { name: 'Assignments' },
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -70,7 +70,7 @@
|
|||||||
<BatchCard :batch="batch" />
|
<BatchCard :batch="batch" />
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
<EmptyState v-else-if="!batches.list.loading" type="Batches" />
|
<EmptyState v-else-if="!batches.list.loading" :type="__('Batches').toLowerCase()" />
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="!batches.list.loading && batches.hasNextPage"
|
v-if="!batches.list.loading && batches.hasNextPage"
|
||||||
|
|||||||
@@ -81,7 +81,7 @@
|
|||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<EmptyState v-else type="Job Openings" />
|
<EmptyState v-else :type="__('Job Openings').toLowerCase()" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -214,7 +214,7 @@
|
|||||||
<div class="mt-20" ref="discussionsContainer">
|
<div class="mt-20" ref="discussionsContainer">
|
||||||
<Discussions
|
<Discussions
|
||||||
v-if="allowDiscussions"
|
v-if="allowDiscussions"
|
||||||
:title="'Questions'"
|
:title="__('Questions')"
|
||||||
:doctype="'Course Lesson'"
|
:doctype="'Course Lesson'"
|
||||||
:docname="lesson.data.name"
|
:docname="lesson.data.name"
|
||||||
:key="lesson.data.name"
|
:key="lesson.data.name"
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ onUnmounted(() => {
|
|||||||
const breadcrumbs = computed(() => {
|
const breadcrumbs = computed(() => {
|
||||||
let crumbs = [
|
let crumbs = [
|
||||||
{
|
{
|
||||||
label: 'Notifications',
|
label: __('Notifications'),
|
||||||
route: {
|
route: {
|
||||||
name: 'Notifications',
|
name: 'Notifications',
|
||||||
},
|
},
|
||||||
@@ -155,7 +155,7 @@ const breadcrumbs = computed(() => {
|
|||||||
|
|
||||||
usePageMeta(() => {
|
usePageMeta(() => {
|
||||||
return {
|
return {
|
||||||
title: 'Notifications',
|
title: __('Notifications'),
|
||||||
icon: brand.favicon,
|
icon: brand.favicon,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -323,12 +323,12 @@ const saveProgram = () => {
|
|||||||
const courseColumns = computed(() => {
|
const courseColumns = computed(() => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
label: 'Title',
|
label: __('Title'),
|
||||||
key: 'course_title',
|
key: 'course_title',
|
||||||
width: 3,
|
width: 3,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'ID',
|
label: __('ID'),
|
||||||
key: 'course',
|
key: 'course',
|
||||||
width: 3,
|
width: 3,
|
||||||
},
|
},
|
||||||
@@ -338,19 +338,19 @@ const courseColumns = computed(() => {
|
|||||||
const memberColumns = computed(() => {
|
const memberColumns = computed(() => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
label: 'Member',
|
label: __('Member'),
|
||||||
key: 'member',
|
key: 'member',
|
||||||
width: 3,
|
width: 3,
|
||||||
align: 'left',
|
align: 'left',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Full Name',
|
label: __('Full Name'),
|
||||||
key: 'full_name',
|
key: 'full_name',
|
||||||
width: 3,
|
width: 3,
|
||||||
align: 'left',
|
align: 'left',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Progress (%)',
|
label: __('Progress (%)'),
|
||||||
key: 'progress',
|
key: 'progress',
|
||||||
width: 3,
|
width: 3,
|
||||||
align: 'right',
|
align: 'right',
|
||||||
@@ -361,11 +361,11 @@ const memberColumns = computed(() => {
|
|||||||
const breadbrumbs = computed(() => {
|
const breadbrumbs = computed(() => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
label: 'Programs',
|
label: __('Programs'),
|
||||||
route: { name: 'Programs' },
|
route: { name: 'Programs' },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: props.programName === 'new' ? 'New Program' : props.programName,
|
label: props.programName === 'new' ? __('New Program') : props.programName,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -82,7 +82,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<EmptyState v-else type="Programs" />
|
<EmptyState v-else :type="__('Programs').toLowerCase()" />
|
||||||
|
|
||||||
<Dialog
|
<Dialog
|
||||||
v-model="showDialog"
|
v-model="showDialog"
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
: __('No Quizzes')
|
: __('No Quizzes')
|
||||||
}}
|
}}
|
||||||
</div>
|
</div>
|
||||||
<FormControl v-model="search" type="text" placeholder="Search">
|
<FormControl v-model="search" type="text" :placeholder="__('Search')">
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<FeatherIcon name="search" class="size-4 text-ink-gray-5" />
|
<FeatherIcon name="search" class="size-4 text-ink-gray-5" />
|
||||||
</template>
|
</template>
|
||||||
@@ -88,7 +88,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</ListSelectBanner>
|
</ListSelectBanner>
|
||||||
</ListView>
|
</ListView>
|
||||||
<EmptyState v-else type="Quizzes" />
|
<EmptyState v-else :type="__('Quizzes').toLowerCase()" />
|
||||||
<div v-if="quizzes.hasNextPage" class="flex justify-center my-5">
|
<div v-if="quizzes.hasNextPage" class="flex justify-center my-5">
|
||||||
<Button @click="quizzes.next()">
|
<Button @click="quizzes.next()">
|
||||||
{{ __('Load More') }}
|
{{ __('Load More') }}
|
||||||
|
|||||||
@@ -16,14 +16,14 @@
|
|||||||
<Tooltip :text="__('Active Members')">
|
<Tooltip :text="__('Active Members')">
|
||||||
<NumberChart
|
<NumberChart
|
||||||
class="border rounded-md"
|
class="border rounded-md"
|
||||||
:config="{ title: 'Signups', value: chartDetails.data.users }"
|
:config="{ title: __('Signups'), value: chartDetails.data.users }"
|
||||||
/>
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip :text="__('Course Enrollments')">
|
<Tooltip :text="__('Course Enrollments')">
|
||||||
<NumberChart
|
<NumberChart
|
||||||
class="border rounded-md"
|
class="border rounded-md"
|
||||||
:config="{
|
:config="{
|
||||||
title: 'Enrollments',
|
title: __('Enrollments'),
|
||||||
value: chartDetails.data.enrollments,
|
value: chartDetails.data.enrollments,
|
||||||
}"
|
}"
|
||||||
/>
|
/>
|
||||||
@@ -122,7 +122,7 @@
|
|||||||
:config="{
|
:config="{
|
||||||
data: courseCompletion.data,
|
data: courseCompletion.data,
|
||||||
title: __('Completions'),
|
title: __('Completions'),
|
||||||
subtitle: 'Course Completion',
|
subtitle: __('Course Completion'),
|
||||||
categoryColumn: 'label',
|
categoryColumn: 'label',
|
||||||
valueColumn: 'value',
|
valueColumn: 'value',
|
||||||
}"
|
}"
|
||||||
|
|||||||
Reference in New Issue
Block a user