mirror of
https://github.com/immich-app/immich
synced 2026-08-15 13:03:57 +00:00
chore: enforce strict equality checks
This commit is contained in:
parent
ee525f159b
commit
dbffd57f02
35 changed files with 54 additions and 45 deletions
|
|
@ -76,6 +76,7 @@ export default typescriptEslint.config([
|
|||
curly: 2,
|
||||
'prettier/prettier': 0,
|
||||
'object-shorthand': ['error', 'always'],
|
||||
eqeqeq: 'error',
|
||||
|
||||
'no-restricted-imports': [
|
||||
'error',
|
||||
|
|
|
|||
|
|
@ -838,7 +838,7 @@ export class AssetRepository {
|
|||
)
|
||||
.$if(!!options.withCoordinates, (qb) => qb.select(['asset_exif.latitude', 'asset_exif.longitude']))
|
||||
.where('asset.deletedAt', options.isTrashed ? 'is not' : 'is', null)
|
||||
.$if(options.visibility == undefined, withDefaultVisibility)
|
||||
.$if(options.visibility === undefined, withDefaultVisibility)
|
||||
.$if(!!options.visibility, (qb) => qb.where('asset.visibility', '=', options.visibility!))
|
||||
.$if(!!options.bbox, (qb) => {
|
||||
const bbox = options.bbox!;
|
||||
|
|
@ -899,7 +899,7 @@ export class AssetRepository {
|
|||
.$if(!!options.isTrashed, (qb) => qb.where('asset.status', '!=', AssetStatus.Deleted))
|
||||
.$if(!!options.tagId, (qb) => withTagId(qb, options.tagId!))
|
||||
.orderBy(
|
||||
options.orderBy == AssetOrderBy.CreatedAt
|
||||
options.orderBy === AssetOrderBy.CreatedAt
|
||||
? sql`"createdAt"`
|
||||
: sql`(asset."localDateTime" AT TIME ZONE 'UTC')::date`,
|
||||
order,
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ export class TelemetryRepository {
|
|||
const unit = 'ms';
|
||||
|
||||
for (const [propName, descriptor] of Object.entries(descriptors)) {
|
||||
const isMethod = typeof descriptor.value == 'function' && propName !== 'constructor';
|
||||
const isMethod = typeof descriptor.value === 'function' && propName !== 'constructor';
|
||||
if (!isMethod) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -321,7 +321,7 @@ export class UserRepository {
|
|||
updatedAt: new Date(),
|
||||
})
|
||||
.where('user.deletedAt', 'is', null)
|
||||
.$if(id != undefined, (eb) => eb.where('user.id', '=', asUuid(id!)));
|
||||
.$if(id !== undefined, (eb) => eb.where('user.id', '=', asUuid(id!)));
|
||||
|
||||
await query.execute();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -549,7 +549,7 @@ export class AuthService extends BaseService {
|
|||
const now = DateTime.now();
|
||||
const updatedAt = DateTime.fromJSDate(session.updatedAt);
|
||||
const diff = now.diff(updatedAt, ['hours']);
|
||||
if (diff.hours > 1 || appVersion != session.appVersion) {
|
||||
if (diff.hours > 1 || appVersion !== session.appVersion) {
|
||||
await this.sessionRepository.update(session.id, {
|
||||
id: session.id,
|
||||
updatedAt: new Date(),
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ const validateRange = (value: number | undefined, min: number, max: number): Non
|
|||
const val = validate(value);
|
||||
|
||||
// check if the value is within the range
|
||||
if (val == null || val < min || val > max) {
|
||||
if (val === null || val < min || val > max) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -372,8 +372,8 @@ export class MetadataService extends BaseService {
|
|||
fileModifiedAt: stats.mtime,
|
||||
|
||||
// Keep unedited assets in sync with the file on disk, but don't overwrite edited dimensions.
|
||||
width: !asset.isEdited || asset.width == null ? assetWidth : undefined,
|
||||
height: !asset.isEdited || asset.height == null ? assetHeight : undefined,
|
||||
width: !asset.isEdited || asset.width === null ? assetWidth : undefined,
|
||||
height: !asset.isEdited || asset.height === null ? assetHeight : undefined,
|
||||
}),
|
||||
async () => {
|
||||
await this.assetRepository.upsertExif({
|
||||
|
|
@ -988,7 +988,7 @@ export class MetadataService extends BaseService {
|
|||
|
||||
// timezone
|
||||
let timeZone = exifTags.zone ?? null;
|
||||
if (timeZone == null && (dateTime?.rawValue?.endsWith('Z') || dateTime?.rawValue?.endsWith('+00:00'))) {
|
||||
if (timeZone === null && (dateTime?.rawValue?.endsWith('Z') || dateTime?.rawValue?.endsWith('+00:00'))) {
|
||||
// exiftool-vendored returns "no timezone" information even though "+00:00" might be set explicitly
|
||||
// https://github.com/photostructure/exiftool-vendored.js/issues/203
|
||||
timeZone = 'UTC+0';
|
||||
|
|
|
|||
|
|
@ -402,8 +402,8 @@ export class StorageTemplateService extends BaseService {
|
|||
const substitutions: Record<string, string> = {
|
||||
filename,
|
||||
ext: extension,
|
||||
filetype: asset.type == AssetType.Image ? 'IMG' : 'VID',
|
||||
filetypefull: asset.type == AssetType.Image ? 'IMAGE' : 'VIDEO',
|
||||
filetype: asset.type === AssetType.Image ? 'IMG' : 'VID',
|
||||
filetypefull: asset.type === AssetType.Image ? 'IMAGE' : 'VIDEO',
|
||||
assetId: asset.id,
|
||||
assetIdShort: asset.id.slice(-12),
|
||||
//just throw into the root if it doesn't belong to an album
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export function asHumanReadable(bytes: number, precision = 1): string {
|
|||
}
|
||||
}
|
||||
|
||||
return `${remainder.toFixed(magnitude == 0 ? 0 : precision)} ${units[magnitude]}`;
|
||||
return `${remainder.toFixed(magnitude === 0 ? 0 : precision)} ${units[magnitude]}`;
|
||||
}
|
||||
|
||||
// if an asset is jsonified in the DB before being returned, its buffer fields will be hex-encoded strings
|
||||
|
|
|
|||
|
|
@ -227,7 +227,7 @@ export const transformOcrBoundingBox = (
|
|||
const { points: transformedPoints, currentWidth, currentHeight } = transformPoints(points, edits, imageDimensions);
|
||||
|
||||
// Reorder points to maintain semantic ordering (topLeft, topRight, bottomRight, bottomLeft)
|
||||
const netRotation = edits.find((e) => e.action == AssetEditAction.Rotate)?.parameters.angle ?? 0 % 360;
|
||||
const netRotation = edits.find((e) => e.action === AssetEditAction.Rotate)?.parameters.angle ?? 0 % 360;
|
||||
const reorderedPoints = reorderQuadPointsForRotation(transformedPoints, netRotation);
|
||||
|
||||
const [p1, p2, p3, p4] = reorderedPoints;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ export default typescriptEslint.config(
|
|||
...eslintPluginSvelte.configs.recommended,
|
||||
eslintPluginUnicorn.configs.recommended,
|
||||
js.configs.recommended,
|
||||
prettier,
|
||||
{
|
||||
plugins: {
|
||||
tscompat: tslintPluginCompat,
|
||||
|
|
@ -158,6 +159,7 @@ export default typescriptEslint.config(
|
|||
'svelte/button-has-type': 'error',
|
||||
'object-shorthand': ['error', 'always'],
|
||||
'svelte/no-navigation-without-resolve': 'off',
|
||||
eqeqeq: 'error',
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ export function useActions(node: HTMLElement | SVGElement, actions: ActionArray)
|
|||
|
||||
return {
|
||||
update(actions: ActionArray) {
|
||||
if ((actions?.length || 0) != actionReturns.length) {
|
||||
if ((actions?.length || 0) !== actionReturns.length) {
|
||||
throw new Error('You must not change the length of an actions array.');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@
|
|||
};
|
||||
|
||||
$effect(() => {
|
||||
if (assetId && previousAssetId != assetId) {
|
||||
if (assetId && previousAssetId !== assetId) {
|
||||
previousAssetId = assetId;
|
||||
}
|
||||
});
|
||||
|
|
@ -168,7 +168,7 @@
|
|||
{/if}
|
||||
</div>
|
||||
|
||||
{#if (index != activityManager.activities.length - 1 && !shouldGroup(activityManager.activities[index].createdAt, activityManager.activities[index + 1].createdAt)) || index === activityManager.activities.length - 1}
|
||||
{#if (index !== activityManager.activities.length - 1 && !shouldGroup(activityManager.activities[index].createdAt, activityManager.activities[index + 1].createdAt)) || index === activityManager.activities.length - 1}
|
||||
<div
|
||||
class="w-full px-2 pt-1 text-right text-sm text-gray-500 dark:text-gray-300"
|
||||
title={new Date(reaction.createdAt).toLocaleDateString(undefined, timeOptions)}
|
||||
|
|
@ -217,7 +217,7 @@
|
|||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{#if (index != activityManager.activities.length - 1 && isTenMinutesApart(activityManager.activities[index].createdAt, activityManager.activities[index + 1].createdAt)) || index === activityManager.activities.length - 1}
|
||||
{#if (index !== activityManager.activities.length - 1 && isTenMinutesApart(activityManager.activities[index].createdAt, activityManager.activities[index + 1].createdAt)) || index === activityManager.activities.length - 1}
|
||||
<div
|
||||
class="w-full px-2 pt-1 text-right text-sm text-gray-500 dark:text-gray-300"
|
||||
title={new Date(reaction.createdAt).toLocaleDateString(navigator.language, timeOptions)}
|
||||
|
|
|
|||
|
|
@ -521,7 +521,7 @@
|
|||
</div>
|
||||
{/if}
|
||||
|
||||
{#if $slideshowState != SlideshowState.None}
|
||||
{#if $slideshowState !== SlideshowState.None}
|
||||
<div class="absolute inset-s-0 top-0 flex w-full justify-start">
|
||||
<SlideshowBar
|
||||
{isFullScreen}
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@
|
|||
<img src={poster} alt="poster" class="m-4 rounded-xl" />
|
||||
|
||||
<div class="flex place-content-center place-items-center">
|
||||
{#if castManager.castState == CastState.BUFFERING}
|
||||
{#if castManager.castState === CastState.BUFFERING}
|
||||
<div class="p-3">
|
||||
<LoadingSpinner />
|
||||
</div>
|
||||
|
|
@ -85,9 +85,9 @@
|
|||
color="primary"
|
||||
shape="round"
|
||||
variant="ghost"
|
||||
icon={castManager.castState == CastState.PLAYING ? mdiPause : mdiPlay}
|
||||
icon={castManager.castState === CastState.PLAYING ? mdiPause : mdiPlay}
|
||||
onclick={() => handlePlayPauseButton()}
|
||||
aria-label={castManager.castState == CastState.PLAYING ? 'Pause' : 'Play'}
|
||||
aria-label={castManager.castState === CastState.PLAYING ? 'Pause' : 'Play'}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
|
|
|
|||
|
|
@ -357,7 +357,7 @@
|
|||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{#if face.person != null}
|
||||
{#if face.person !== null}
|
||||
<div class="absolute inset-e-[-3px] top-8 size-5 rounded-full">
|
||||
<IconButton
|
||||
shape="round"
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
const id = generateId();
|
||||
|
||||
const onInput = () => {
|
||||
if (lat != null && lng != null) {
|
||||
if (lat !== undefined && lng !== undefined) {
|
||||
onUpdate(lat, lng);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -287,7 +287,7 @@
|
|||
if (previousStyle) {
|
||||
// Preserves the custom map markers from the previous style when the theme is switched
|
||||
// Required until https://github.com/dimfeld/svelte-maplibre/issues/146 is fixed
|
||||
const customLayers = previousStyle.layers.filter((l) => l.type == 'fill' && l.source == 'geojson');
|
||||
const customLayers = previousStyle.layers.filter((l) => l.type === 'fill' && l.source === 'geojson');
|
||||
const layers = nextStyle.layers.concat(customLayers);
|
||||
const sources = nextStyle.sources;
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
let { key, values = {}, children }: Props = $props();
|
||||
|
||||
const getLocale = (locale?: string | null) => {
|
||||
if (locale == null) {
|
||||
if (!locale) {
|
||||
throw new Error('Cannot format a message without first setting the initial locale.');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ describe('i18n', () => {
|
|||
const languageFiles = readdirSync('../i18n').sort();
|
||||
for (const filename of languageFiles) {
|
||||
test(`${filename} should have a loader`, async () => {
|
||||
if (!filename.endsWith('.json') || filename == 'package.json') {
|
||||
if (!filename.endsWith('.json') || filename === 'package.json') {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ export abstract class VirtualScrollManager {
|
|||
}
|
||||
|
||||
#setHeaderHeight(value: number) {
|
||||
if (this.#headerHeight == value) {
|
||||
if (this.#headerHeight === value) {
|
||||
return false;
|
||||
}
|
||||
this.#headerHeight = value;
|
||||
|
|
@ -67,7 +67,7 @@ export abstract class VirtualScrollManager {
|
|||
}
|
||||
|
||||
#setGap(value: number) {
|
||||
if (this.#gap == value) {
|
||||
if (this.#gap === value) {
|
||||
return false;
|
||||
}
|
||||
this.#gap = value;
|
||||
|
|
@ -79,7 +79,7 @@ export abstract class VirtualScrollManager {
|
|||
}
|
||||
|
||||
#setRowHeight(value: number) {
|
||||
if (this.#rowHeight == value) {
|
||||
if (this.#rowHeight === value) {
|
||||
return false;
|
||||
}
|
||||
this.#rowHeight = value;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
const { point, assetCount, onClose }: Props = $props();
|
||||
|
||||
const hasExistingLocations = $derived(
|
||||
// eslint-disable-next-line eqeqeq
|
||||
assetMultiSelectManager.assets.some((asset) => asset.latitude != null || asset.longitude != null),
|
||||
);
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ function zoneOptionForDate(zone: string, date: string) {
|
|||
|
||||
function sortTwoZones(zoneA: ZoneOption, zoneB: ZoneOption) {
|
||||
const offsetDifference = zoneA.offsetMinutes - zoneB.offsetMinutes;
|
||||
if (offsetDifference != 0) {
|
||||
if (offsetDifference !== 0) {
|
||||
return offsetDifference;
|
||||
}
|
||||
return zoneA.value.localeCompare(zoneB.value, undefined, { sensitivity: 'base' });
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ function createUploadStore() {
|
|||
const updateAssetMap = (id: string, mapper: (assets: UploadAsset) => UploadAsset) => {
|
||||
uploadAssets.update((uploadingAssets) => {
|
||||
return uploadingAssets.map((asset) => {
|
||||
if (asset.id == id) {
|
||||
if (asset.id === id) {
|
||||
return mapper(asset);
|
||||
}
|
||||
return asset;
|
||||
|
|
@ -111,7 +111,7 @@ function createUploadStore() {
|
|||
});
|
||||
}
|
||||
|
||||
return uploadingAsset.filter((a) => a.id != id);
|
||||
return uploadingAsset.filter((a) => a.id !== id);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ const undoDeleteAssets = async (onUndoDelete: OnUndoDelete, assets: TimelineAsse
|
|||
* @param {StackResponse} stackResponse - The stack response containing the stack and assets to delete.
|
||||
*/
|
||||
export function updateStackedAssetInTimeline(timelineManager: TimelineManager, { stack, toDeleteIds }: StackResponse) {
|
||||
if (stack == undefined) {
|
||||
if (stack === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@ const metadataFields = [
|
|||
titleKey: 'gps',
|
||||
keys: ['latitude', 'longitude'],
|
||||
render: (asset, $t) =>
|
||||
// eslint-disable-next-line eqeqeq
|
||||
asset.exifInfo?.latitude != null && asset.exifInfo?.longitude != null
|
||||
? `${asset.exifInfo.latitude.toFixed(4)}, ${asset.exifInfo.longitude.toFixed(4)}`
|
||||
: $t('unknown'),
|
||||
|
|
@ -173,18 +174,21 @@ const metadataFields = [
|
|||
icon: mdiCameraIris,
|
||||
titleKey: 'f_number',
|
||||
keys: ['fNumber'],
|
||||
// eslint-disable-next-line eqeqeq
|
||||
render: (asset, $t) => (asset.exifInfo?.fNumber == null ? $t('unknown') : `f/${asset.exifInfo.fNumber.toFixed(1)}`),
|
||||
},
|
||||
{
|
||||
icon: mdiRayStartArrow,
|
||||
titleKey: 'focal_length',
|
||||
keys: ['focalLength'],
|
||||
// eslint-disable-next-line eqeqeq
|
||||
render: (asset, $t) => (asset.exifInfo?.focalLength == null ? $t('unknown') : `${asset.exifInfo.focalLength} mm`),
|
||||
},
|
||||
{
|
||||
icon: mdiBrightness6,
|
||||
titleKey: 'iso',
|
||||
keys: ['iso'],
|
||||
// eslint-disable-next-line eqeqeq
|
||||
render: (asset, $t) => (asset.exifInfo?.iso == null ? $t('unknown') : `ISO ${asset.exifInfo.iso}`),
|
||||
},
|
||||
{
|
||||
|
|
@ -203,6 +207,7 @@ const metadataFields = [
|
|||
icon: mdiStarOutline,
|
||||
titleKey: 'rating',
|
||||
keys: ['rating'],
|
||||
// eslint-disable-next-line eqeqeq
|
||||
render: (asset, $t) => (asset.exifInfo?.rating == null ? $t('unknown') : `${asset.exifInfo.rating} stars`),
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ export function currentUrlReplaceAssetId(assetId: string) {
|
|||
// always remove the assetGridScrollTargetParams
|
||||
params.delete('at');
|
||||
const paramsString = params.toString();
|
||||
const searchparams = paramsString == '' ? '' : '?' + params.toString();
|
||||
const searchparams = paramsString === '' ? '' : '?' + params.toString();
|
||||
// this contains special casing for the /photos/:assetId photos route, which hangs directly
|
||||
// off / instead of a subpath, unlike every other asset-containing route.
|
||||
return isPhotosRoute(page.route.id)
|
||||
|
|
|
|||
|
|
@ -183,8 +183,8 @@ export const toTimelineAsset = (unknownAsset: AssetResponseDto | TimelineAsset):
|
|||
isFavorite: assetResponse.isFavorite,
|
||||
visibility: assetResponse.visibility,
|
||||
isTrashed: assetResponse.isTrashed,
|
||||
isVideo: assetResponse.type == AssetTypeEnum.Video,
|
||||
isImage: assetResponse.type == AssetTypeEnum.Image,
|
||||
isVideo: assetResponse.type === AssetTypeEnum.Video,
|
||||
isImage: assetResponse.type === AssetTypeEnum.Image,
|
||||
stack: assetResponse.stack || null,
|
||||
duration: assetResponse.duration || null,
|
||||
projectionType: assetResponse.exifInfo?.projectionType || null,
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@
|
|||
|
||||
const onNameChangeSubmit = async (name: string, targetPerson: PersonResponseDto) => {
|
||||
try {
|
||||
if (name == targetPerson.name) {
|
||||
if (name === targetPerson.name) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@
|
|||
} else if ($page.params.assetId) {
|
||||
previousRoute = Route.viewPerson(data.person);
|
||||
}
|
||||
if (action == 'merge') {
|
||||
if (action === 'merge') {
|
||||
viewMode = PersonPageViewMode.MERGE_PEOPLE;
|
||||
}
|
||||
|
||||
|
|
@ -180,7 +180,7 @@
|
|||
|
||||
const [, personToBeMergedInto] = result;
|
||||
|
||||
if (personToBeMergedInto.name != personName && person.id === personToBeMergedInto.id) {
|
||||
if (personToBeMergedInto.name !== personName && person.id === personToBeMergedInto.id) {
|
||||
await updateAssetCount();
|
||||
return { merged: true };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@
|
|||
personIds.map(async (personId) => {
|
||||
const person = await getPerson({ id: personId });
|
||||
|
||||
if (person.name == '') {
|
||||
if (person.name === '') {
|
||||
return $t('no_name');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@
|
|||
<SettingsLanguageSelector showSettingDescription />
|
||||
|
||||
<Field label={$t('use_browser_locale')} description={$t('use_browser_locale_description')}>
|
||||
<Switch checked={$locale == 'default'} onCheckedChange={handleToggleLocaleBrowser} />
|
||||
<Switch checked={$locale === 'default'} onCheckedChange={handleToggleLocaleBrowser} />
|
||||
<Text size="small" class="mt-2 font-mono text-sm">{selectedDate}</Text>
|
||||
</Field>
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
};
|
||||
|
||||
const preAction = async (payload: Action) => {
|
||||
if (payload.type == 'trash') {
|
||||
if (payload.type === 'trash') {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
||||
(await navigateToAsset(assetCursor?.nextAsset)) ||
|
||||
(await navigateToAsset(assetCursor?.previousAsset)) ||
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@
|
|||
description=""
|
||||
bind:value={configToEdit.job[queueName].concurrency}
|
||||
required={true}
|
||||
isEdited={configToEdit.job[queueName].concurrency != config.job[queueName].concurrency}
|
||||
isEdited={configToEdit.job[queueName].concurrency !== config.job[queueName].concurrency}
|
||||
/>
|
||||
{:else}
|
||||
<SettingInputField
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@
|
|||
);
|
||||
|
||||
const handleNextClicked = async () => {
|
||||
if (nextStepIndex == -1) {
|
||||
if (nextStepIndex === -1) {
|
||||
if (authManager.user.isAdmin) {
|
||||
await updateAdminOnboarding({ adminOnboardingUpdateDto: { isOnboarded: true } });
|
||||
await serverConfigManager.loadServerConfig();
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
{$t('onboarding_welcome_user', { values: { user: authManager.user.name } })}
|
||||
</p>
|
||||
<p class="pb-6 text-3xl font-light">
|
||||
{userRole == OnboardingRole.SERVER
|
||||
{userRole === OnboardingRole.SERVER
|
||||
? $t('onboarding_server_welcome_description')
|
||||
: $t('onboarding_user_welcome_description')}
|
||||
</p>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue