commit
e56e7ac0cc
@ -0,0 +1,433 @@ |
||||
<script setup> |
||||
import { ref, watch } from "vue" |
||||
import { useI18n } from "vue-i18n" |
||||
import Color from "colorjs.io" |
||||
import SectionHeader from "../layout/SectionHeader.vue" |
||||
import ColorThemeSelector from "../platform/ColorThemeSelector.vue" |
||||
import BaseColorPicker from "../basecomponents/BaseColorPicker.vue" |
||||
import BaseButton from "../basecomponents/BaseButton.vue" |
||||
import BaseDialogConfirmCancel from "../basecomponents/BaseDialogConfirmCancel.vue" |
||||
import BaseInputText from "../basecomponents/BaseInputText.vue" |
||||
import colorThemeService from "../../services/colorThemeService" |
||||
import { useNotification } from "../../composables/notification" |
||||
import { useTheme } from "../../composables/theme" |
||||
|
||||
const { showSuccessNotification, showErrorNotification } = useNotification() |
||||
|
||||
const { getColorTheme, getColors, setColors, makeGradient, makeTextWithContrast, checkColorContrast } = useTheme() |
||||
|
||||
const { t } = useI18n() |
||||
|
||||
const isAdvancedMode = ref(false) |
||||
|
||||
const themeSelectorEl = ref() |
||||
|
||||
const selectedThemeIri = ref() |
||||
const newThemeSelected = ref() |
||||
|
||||
let colorPrimary = getColorTheme("--color-primary-base") |
||||
let colorPrimaryGradient = getColorTheme("--color-primary-gradient") |
||||
let colorPrimaryButtonText = getColorTheme("--color-primary-button-text") |
||||
let colorPrimaryButtonAlternativeText = getColorTheme("--color-primary-button-alternative-text") |
||||
|
||||
let colorSecondary = getColorTheme("--color-secondary-base") |
||||
let colorSecondaryGradient = getColorTheme("--color-secondary-gradient") |
||||
let colorSecondaryButtonText = getColorTheme("--color-secondary-button-text") |
||||
|
||||
let colorTertiary = getColorTheme("--color-tertiary-base") |
||||
let colorTertiaryGradient = getColorTheme("--color-tertiary-gradient") |
||||
let colorTertiaryButtonText = getColorTheme("--color-tertiary-button-text") |
||||
|
||||
let colorSuccess = getColorTheme("--color-success-base") |
||||
let colorSuccessGradient = getColorTheme("--color-success-gradient") |
||||
let colorSuccessButtonText = getColorTheme("--color-success-button-text") |
||||
|
||||
let colorInfo = getColorTheme("--color-info-base") |
||||
let colorInfoGradient = getColorTheme("--color-info-gradient") |
||||
let colorInfoButtonText = getColorTheme("--color-info-button-text") |
||||
|
||||
let colorWarning = getColorTheme("--color-warning-base") |
||||
let colorWarningGradient = getColorTheme("--color-warning-gradient") |
||||
let colorWarningButtonText = getColorTheme("--color-warning-button-text") |
||||
|
||||
let colorDanger = getColorTheme("--color-danger-base") |
||||
let colorDangerGradient = getColorTheme("--color-danger-gradient") |
||||
let colorDangerButtonText = getColorTheme("--color-danger-button-text") |
||||
|
||||
let formColor = getColorTheme("--color-form-base") |
||||
|
||||
function onChangeTheme(colorTheme) { |
||||
newThemeSelected.value = colorTheme |
||||
|
||||
if (colorTheme) { |
||||
setColors(colorTheme.variables) |
||||
} |
||||
} |
||||
|
||||
const dialogCreateVisible = ref(false) |
||||
const themeTitle = ref() |
||||
|
||||
async function onClickSelectColorTheme() { |
||||
if (selectedThemeIri.value) { |
||||
await colorThemeService.changePlatformColorTheme(selectedThemeIri.value) |
||||
} |
||||
} |
||||
|
||||
async function onClickUpdate() { |
||||
try { |
||||
const updatedTheme = await colorThemeService.update({ |
||||
iri: selectedThemeIri.value, |
||||
title: themeTitle.value, |
||||
colors: getColors(), |
||||
}) |
||||
|
||||
showSuccessNotification(t("Color updated")) |
||||
|
||||
await themeSelectorEl.value.loadThemes() |
||||
|
||||
selectedThemeIri.value = updatedTheme["@id"] |
||||
} catch (error) { |
||||
showErrorNotification(error) |
||||
} |
||||
} |
||||
|
||||
async function onClickCreate() { |
||||
try { |
||||
if (!themeTitle.value.trim()) { |
||||
return |
||||
} |
||||
|
||||
const updatedTheme = await colorThemeService.create({ |
||||
title: themeTitle.value, |
||||
colors: getColors(), |
||||
}) |
||||
|
||||
showSuccessNotification(t("Color updated")) |
||||
|
||||
await themeSelectorEl.value.loadThemes() |
||||
|
||||
selectedThemeIri.value = updatedTheme["@id"] |
||||
} catch (error) { |
||||
showErrorNotification(error) |
||||
} |
||||
|
||||
dialogCreateVisible.value = false |
||||
} |
||||
|
||||
watch(colorPrimary, (newValue) => { |
||||
colorPrimaryGradient.value = makeGradient(newValue) |
||||
colorPrimaryButtonText.value = newValue |
||||
colorPrimaryButtonAlternativeText.value = makeTextWithContrast(newValue) |
||||
|
||||
colorPrimaryButtonAlternativeTextError.value = checkColorContrast(newValue, colorPrimaryButtonText.value) |
||||
}) |
||||
|
||||
watch(colorSecondary, (newValue) => { |
||||
colorSecondaryGradient.value = makeGradient(newValue) |
||||
colorSecondaryButtonText.value = makeTextWithContrast(newValue) |
||||
|
||||
colorSecondaryButtonTextError.value = checkColorContrast(newValue, colorSecondaryButtonText.value) |
||||
}) |
||||
|
||||
watch(colorTertiary, (newValue) => { |
||||
colorTertiaryButtonText.value = newValue |
||||
colorTertiaryGradient.value = makeGradient(newValue) |
||||
}) |
||||
|
||||
watch(colorSuccess, (newValue) => { |
||||
colorSuccessGradient.value = makeGradient(newValue) |
||||
colorSuccessButtonText.value = makeTextWithContrast(newValue) |
||||
|
||||
colorSuccessButtonTextError.value = checkColorContrast(newValue, colorSuccessButtonText.value) |
||||
}) |
||||
|
||||
watch(colorInfo, (newValue) => { |
||||
colorInfoGradient.value = makeGradient(newValue) |
||||
colorInfoButtonText.value = makeTextWithContrast(newValue) |
||||
|
||||
colorInfoButtonTextError.value = checkColorContrast(newValue, colorInfoButtonText.value) |
||||
}) |
||||
|
||||
watch(colorWarning, (newValue) => { |
||||
colorWarningGradient.value = makeGradient(newValue) |
||||
colorWarningButtonText.value = makeTextWithContrast(newValue) |
||||
|
||||
colorWarningButtonTextError.value = checkColorContrast(newValue, colorWarningButtonText.value) |
||||
}) |
||||
|
||||
watch(colorDanger, (newValue) => { |
||||
colorDangerGradient.value = makeGradient(newValue) |
||||
colorDangerButtonText.value = makeTextWithContrast(newValue) |
||||
}) |
||||
|
||||
// check for contrast of text |
||||
const colorPrimaryButtonTextError = ref("") |
||||
watch( |
||||
colorPrimaryButtonText, |
||||
(newValue) => (colorPrimaryButtonTextError.value = checkColorContrast(new Color("white"), newValue)), |
||||
) |
||||
|
||||
const colorPrimaryButtonAlternativeTextError = ref("") |
||||
watch( |
||||
colorPrimaryButtonAlternativeText, |
||||
(newValue) => (colorPrimaryButtonAlternativeTextError.value = checkColorContrast(colorPrimary.value, newValue)), |
||||
) |
||||
|
||||
const colorSecondaryButtonTextError = ref("") |
||||
watch( |
||||
colorSecondaryButtonText, |
||||
(newValue) => (colorSecondaryButtonTextError.value = checkColorContrast(colorSecondary.value, newValue)), |
||||
) |
||||
|
||||
const colorTertiaryButtonTextError = ref("") |
||||
watch( |
||||
colorTertiaryButtonText, |
||||
(newValue) => (colorTertiaryButtonTextError.value = checkColorContrast(colorTertiary.value, newValue)), |
||||
) |
||||
|
||||
const colorSuccessButtonTextError = ref("") |
||||
watch( |
||||
colorSuccessButtonText, |
||||
(newValue) => (colorSuccessButtonTextError.value = checkColorContrast(colorSuccess.value, newValue)), |
||||
) |
||||
|
||||
const colorInfoButtonTextError = ref("") |
||||
watch( |
||||
colorInfoButtonText, |
||||
(newValue) => (colorInfoButtonTextError.value = checkColorContrast(colorInfo.value, newValue)), |
||||
) |
||||
|
||||
const colorWarningButtonTextError = ref("") |
||||
watch( |
||||
colorWarningButtonText, |
||||
(newValue) => (colorWarningButtonTextError.value = checkColorContrast(colorWarning.value, newValue)), |
||||
) |
||||
|
||||
const colorDangerButtonTextError = ref("") |
||||
watch( |
||||
colorDangerButtonText, |
||||
(newValue) => (colorDangerButtonTextError.value = checkColorContrast(new Color("white"), newValue)), |
||||
) |
||||
</script> |
||||
|
||||
<template> |
||||
<ColorThemeSelector |
||||
ref="themeSelectorEl" |
||||
v-model="selectedThemeIri" |
||||
@change="onChangeTheme" |
||||
/> |
||||
|
||||
<SectionHeader |
||||
:title="t('Modify color theme')" |
||||
size="6" |
||||
> |
||||
<BaseButton |
||||
:label="isAdvancedMode ? t('Hide advanced mode') : t('Show advanced mode')" |
||||
icon="cog" |
||||
type="black" |
||||
@click="isAdvancedMode = !isAdvancedMode" |
||||
/> |
||||
</SectionHeader> |
||||
|
||||
<form class="admin-colors__form-fields"> |
||||
<!-- Advanced mode --> |
||||
<div v-show="isAdvancedMode"> |
||||
<div class="field-group"> |
||||
<BaseColorPicker |
||||
v-model="colorPrimary" |
||||
:label="t('Primary color')" |
||||
/> |
||||
<BaseColorPicker |
||||
v-model="colorPrimaryGradient" |
||||
:label="t('Primary color hover/background')" |
||||
/> |
||||
<BaseColorPicker |
||||
v-model="colorPrimaryButtonText" |
||||
:error="colorPrimaryButtonTextError" |
||||
:label="t('Primary color button text')" |
||||
/> |
||||
<BaseColorPicker |
||||
v-model="colorPrimaryButtonAlternativeText" |
||||
:error="colorPrimaryButtonAlternativeTextError" |
||||
:label="t('Primary color button alternative text')" |
||||
/> |
||||
</div> |
||||
|
||||
<div class="field-group"> |
||||
<BaseColorPicker |
||||
v-model="colorSecondary" |
||||
:label="t('Secondary color')" |
||||
/> |
||||
<BaseColorPicker |
||||
v-model="colorSecondaryGradient" |
||||
:label="t('Secondary color hover/background')" |
||||
/> |
||||
<BaseColorPicker |
||||
v-model="colorSecondaryButtonText" |
||||
:error="colorSecondaryButtonTextError" |
||||
:label="t('Secondary color button text')" |
||||
/> |
||||
</div> |
||||
|
||||
<div class="field-group"> |
||||
<BaseColorPicker |
||||
v-model="colorTertiary" |
||||
:label="t('Tertiary color')" |
||||
/> |
||||
<BaseColorPicker |
||||
v-model="colorTertiaryGradient" |
||||
:label="t('Tertiary color hover/background')" |
||||
/> |
||||
</div> |
||||
|
||||
<div class="field-group"> |
||||
<BaseColorPicker |
||||
v-model="colorSuccess" |
||||
:label="t('Success color')" |
||||
/> |
||||
<BaseColorPicker |
||||
v-model="colorSuccessGradient" |
||||
:label="t('Success color hover/background')" |
||||
/> |
||||
<BaseColorPicker |
||||
v-model="colorSuccessButtonText" |
||||
:error="colorSuccessButtonTextError" |
||||
:label="t('Success color button text')" |
||||
/> |
||||
</div> |
||||
|
||||
<div class="field-group"> |
||||
<BaseColorPicker |
||||
v-model="colorInfo" |
||||
:label="t('Info color')" |
||||
/> |
||||
<BaseColorPicker |
||||
v-model="colorInfoGradient" |
||||
:label="t('Info color hover/background')" |
||||
/> |
||||
<BaseColorPicker |
||||
v-model="colorInfoButtonText" |
||||
:error="colorInfoButtonTextError" |
||||
:label="t('Info color button text')" |
||||
/> |
||||
</div> |
||||
|
||||
<div class="field-group"> |
||||
<BaseColorPicker |
||||
v-model="colorWarning" |
||||
:label="t('Warning color')" |
||||
/> |
||||
<BaseColorPicker |
||||
v-model="colorWarningGradient" |
||||
:label="t('Warning color hover/background')" |
||||
/> |
||||
<BaseColorPicker |
||||
v-model="colorWarningButtonText" |
||||
:error="colorWarningButtonTextError" |
||||
:label="t('Warning color button text')" |
||||
/> |
||||
</div> |
||||
|
||||
<div class="field-group"> |
||||
<BaseColorPicker |
||||
v-model="colorDanger" |
||||
:label="t('Danger color')" |
||||
/> |
||||
<BaseColorPicker |
||||
v-model="colorDangerGradient" |
||||
:label="t('Danger color hover/background')" |
||||
/> |
||||
</div> |
||||
|
||||
<div class="field-group"> |
||||
<BaseColorPicker |
||||
v-model="formColor" |
||||
:label="t('Form outline color')" |
||||
/> |
||||
</div> |
||||
</div> |
||||
|
||||
<!-- Simple mode --> |
||||
<div v-show="!isAdvancedMode"> |
||||
<div class="field-group"> |
||||
<BaseColorPicker |
||||
v-model="colorPrimary" |
||||
:label="t('Primary color')" |
||||
/> |
||||
<BaseColorPicker |
||||
v-model="colorSecondary" |
||||
:label="t('Secondary color')" |
||||
/> |
||||
<BaseColorPicker |
||||
v-model="colorTertiary" |
||||
:label="t('Tertiary color')" |
||||
/> |
||||
</div> |
||||
|
||||
<div class="field-group"> |
||||
<BaseColorPicker |
||||
v-model="colorSuccess" |
||||
:label="t('Success color')" |
||||
/> |
||||
<BaseColorPicker |
||||
v-model="colorInfo" |
||||
:label="t('Info color')" |
||||
/> |
||||
<BaseColorPicker |
||||
v-model="colorWarning" |
||||
:label="t('Warning color')" |
||||
/> |
||||
<BaseColorPicker |
||||
v-model="colorDanger" |
||||
:label="t('Danger color')" |
||||
/> |
||||
</div> |
||||
|
||||
<div class="field-group"> |
||||
<BaseColorPicker |
||||
v-model="formColor" |
||||
:label="t('Form outline color')" |
||||
/> |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="field-group"> |
||||
<BaseButton |
||||
:disabled="!selectedThemeIri" |
||||
:label="t('Select as current theme')" |
||||
icon="save" |
||||
type="primary" |
||||
@click="onClickSelectColorTheme" |
||||
/> |
||||
|
||||
<BaseButton |
||||
:disabled="!selectedThemeIri" |
||||
:label="t('Save')" |
||||
icon="send" |
||||
type="primary" |
||||
@click="onClickUpdate" |
||||
/> |
||||
|
||||
<BaseButton |
||||
:label="t('Save as new theme')" |
||||
icon="send" |
||||
type="primary" |
||||
@click="dialogCreateVisible = true" |
||||
/> |
||||
</div> |
||||
</form> |
||||
|
||||
<BaseDialogConfirmCancel |
||||
v-model:is-visible="dialogCreateVisible" |
||||
:cancel-label="t('Cancel')" |
||||
:confirm-label="t('Save')" |
||||
:title="t('New color theme')" |
||||
@confirm-clicked="onClickCreate" |
||||
@cancel-clicked="dialogCreateVisible = false" |
||||
> |
||||
<BaseInputText |
||||
v-model="themeTitle" |
||||
:label="t('Title')" |
||||
/> |
||||
</BaseDialogConfirmCancel> |
||||
</template> |
Loading…
Reference in new issue