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