diff --git a/packages/piveau-hub-ui-modules/lib/data-provider-interface/HappyFlowComponents/ui/Dropdown.vue b/packages/piveau-hub-ui-modules/lib/data-provider-interface/HappyFlowComponents/ui/Dropdown.vue index 84b1d77fe3e95dcc47e3c14e6f2bdba71c69b6c2..b0be0b46980d8e5917a5b58798512e0aff7a55ac 100644 --- a/packages/piveau-hub-ui-modules/lib/data-provider-interface/HappyFlowComponents/ui/Dropdown.vue +++ b/packages/piveau-hub-ui-modules/lib/data-provider-interface/HappyFlowComponents/ui/Dropdown.vue @@ -22,7 +22,7 @@ item.headers) }}</div> <div v-for="(itemInner, i) in item.list" class="dpiV3_btnWrap"> - <button @click="handleMultiClick(itemInner.alt_label['de'], $event, parentCategory(item.headers))" + <button @click="handleMultiClick(itemInner, $event, parentCategory(item.headers))" @keydown.enter=" handleKeyDownMulti(itemInner, $event) " @keydown.space.prevent=" @@ -266,8 +266,11 @@ const handleKeyUp = (item, e) => { } }; const handleMultiClick = (item, e, header) => { - console.log("Item:", item, "Header:", header) - inputText.value = item + " (" + header + ")"; + + emit('valueSent', item); + console.log("Item:", item.alt_label['de'], "Header:", header, item) + + inputText.value = item.alt_label['de'] + " (" + header + ")"; } const handleClick = (item, e) => { diff --git a/packages/piveau-hub-ui-modules/lib/data-provider-interface/HappyFlowComponents/ui/TextAreaV3.vue b/packages/piveau-hub-ui-modules/lib/data-provider-interface/HappyFlowComponents/ui/TextAreaV3.vue index 597f2a2384acb3f684295c3bce077f628b499162..f41bfcf138524b0b5b0d52cbc05ebb7e0b6a26ff 100644 --- a/packages/piveau-hub-ui-modules/lib/data-provider-interface/HappyFlowComponents/ui/TextAreaV3.vue +++ b/packages/piveau-hub-ui-modules/lib/data-provider-interface/HappyFlowComponents/ui/TextAreaV3.vue @@ -26,9 +26,7 @@ <div class="dpiV3_hintText copy-small-regular" v-if="hint && !showError"> <span>This is a supporting message.</span> </div> - <div class="dpiV3_errorText copy-small-regular" v-if="showError"> - <span>This is an error message.</span> - </div> + </div> </div> </template> diff --git a/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/ContactPage.vue b/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/ContactPage.vue index dfbb889a116d1779afc1c949147c235f8f3e08a6..84e6a54c68122a6cd23433f6a1edf95bef63a27d 100644 --- a/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/ContactPage.vue +++ b/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/ContactPage.vue @@ -41,21 +41,28 @@ </div> </div> </div> - <InputField @input="handleInput($event, 'vcard:fn')" :addOnText="false" :datePicker="false" :infoIcon="false" + <InputField @input="handleInput($event, 'vcard:fn', 1)" :addOnText="false" :datePicker="false" :infoIcon="false" :placeholder="$t('message.dataupload.datasets.dcat:contactPoint.nameInput.placeholder') " :preIcon="false" inputFieldSize="large" :initialHintText="false" - :label="$t('message.dataupload.datasets.dcat:contactPoint.nameInput.title')" :showEndIcon="false" /> - <InputField @input="handleInput($event, 'vcard:hasEmail')" :addOnText="false" :datePicker="false" :infoIcon="false" - :placeholder="$t('message.dataupload.datasets.dcat:contactPoint.mailInput.placeholder') + :label="$t('message.dataupload.datasets.dcat:contactPoint.nameInput.title')" :showEndIcon="false" + :showError="arr[0].isValid === false && validInputs[1] === false" /> + <InputField @input="handleInput($event, 'vcard:hasEmail', 2)" :addOnText="false" :datePicker="false" + :infoIcon="false" :placeholder="$t('message.dataupload.datasets.dcat:contactPoint.mailInput.placeholder') " :preIcon="false" inputFieldSize="large" :initialHintText="false" - :label="$t('message.dataupload.datasets.dcat:contactPoint.mailInput.title')" :showEndIcon="false" /> - <InputField @input="handleInput($event, 'vcard:hasTelephone')" :addOnText="false" :datePicker="false" + :label="$t('message.dataupload.datasets.dcat:contactPoint.mailInput.title')" :showEndIcon="false" + :showError="arr[0].isValid === false && validInputs[2] === false" /> + <InputField @input="handleInput($event, 'vcard:hasTelephone', 3)" :addOnText="false" :datePicker="false" :infoIcon="false" :placeholder="$t('message.dataupload.datasets.dcat:contactPoint.telInput.placeholder') " :preIcon="false" inputFieldSize="large" :initialHintText="false" :label="$t('message.dataupload.datasets.dcat:contactPoint.telInput.title') - " :showEndIcon="false" /> + " :showEndIcon="false" :showError="arr[0].isValid === false && validInputs[3] === false" /> + <div> {{ $t("message.dataupload.datasets.dcat:contactPoint.descriptionBottom") }} </div> + <div class="dpiV3_errormsgWrapper" v-if="arr.find(obj => obj.isValid === false)"> + <PhWarning :size="16" weight="fill" /> + <span class="copy-mini-regular">Bitte füllen Sie alle Pflichtfelder aus, bevor Sie fortfahren.</span> + </div> </div> </template> @@ -63,6 +70,7 @@ import { ref } from "vue"; import InputField from "../HappyFlowComponents/ui/InputField.vue"; import TextButtonSmall from "../HappyFlowComponents/ui/TextButtonSmall.vue"; +import { PhWarning } from "@phosphor-icons/vue"; const props = defineProps({ context: Object, }); @@ -76,16 +84,30 @@ const datenbereitsteller = [ "Mobilitätsreferat - Verkehrs- und Verhaltensdaten", "verkehrsdaten.mor@muenchen.de", ]; + +let validInputs = ref({ 1: false, 2: false, 3: false }) const arr = ref([ - { "foaf:name": "" }, - { "foaf:mbox": "" }, - { "foaf:homepage": "" }, + { isValid: 'unset', "vcard:fn": "", "vcard:hasEmail": "", "vcard:hasTelephone": "" }, ]); -const handleInput = (e, namespace) => { +props.context.node.input(arr) + +const handleInput = (e, namespace, iIndex) => { + if (e.target.value != "") { + validInputs.value[iIndex] = true + if (validInputs.value[1] && validInputs.value[2] && validInputs.value[3]) { + arr.value[0].isValid = true + } + } else { + validInputs.value[iIndex] = false + if (!validInputs.value[1] || !validInputs.value[2] || !validInputs.value[3]) { + arr.value[0].isValid = false + } + } + const newValue = e.target.value; // Aktualisiere nur den Wert des entsprechenden Namensraums - arr.value = arr.value.map((item) => { + arr.value = arr.value.map(item => { if (namespace in item) { return { ...item, [namespace]: newValue }; // Aktualisiere nur den spezifischen Wert } @@ -178,4 +200,16 @@ const handleInput = (e, namespace) => { color: var(--neutral-80, #3d4952); } } +.dpiV3_errormsgWrapper { + width: 375px; + position: absolute; + right: 10px; + bottom: 104px; + color: var(--text-error, #A9242C); + + span { + color: var(--text-error, #A9242C); + text-align: right; + } +} </style> diff --git a/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/DiscoverabilityPage.vue b/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/DiscoverabilityPage.vue index 3d848be9ea13cc990aea219878ce083cf14f2210..1fd213ae7005d8ae09428662bd4c482d885f03a8 100644 --- a/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/DiscoverabilityPage.vue +++ b/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/DiscoverabilityPage.vue @@ -7,11 +7,18 @@ <div class="dpiV3_findabilityThemesWrap"> <Chip v-for="(item, index) in URIList" :key="index" :text="item.pref_label.de" :data="{ '@value': item.value, URI: item.URI }" - :setup="{ '@type': 'select', '@inTable': false, '@findability': true }"> + :setup="{ '@type': 'select', '@inTable': false, '@findability': true }" @click="addTolist(item)"> </Chip> </div> <!-- <details v-if="URIList.length > 0">{{ URIList[1] }}</details> --> + <div class="dpiV3_errormsgWrapper" v-if="chosenItems.find(obj => obj.isValid === false)"> + <PhWarning :size="16" weight="fill" /> + <span class="copy-mini-regular">Bitte wählen Sie mindestens eine Kategorie aus, bevor Sie + fortfahren.</span> + </div> + + <!-- <div class="dpiV3_interactionWrap"> <TextButtonLarge buttonText="Abbrechen" /> <div class="dpiV3_actionButtonWrap"> @@ -28,20 +35,49 @@ import Chip from "../HappyFlowComponents/ui/Chip.vue"; import { ref, onMounted } from 'vue'; import { getCurrentInstance } from "vue"; import { getDatasetCategories } from "../HappyFlowComponents/services/dpiV3_apis"; +import { PhWarning } from "@phosphor-icons/vue"; let URIList = ref([]); let instance = getCurrentInstance().appContext.app.config.globalProperties.$env; +let chosenItems = ref([{ isValid: 'unset' }]) +const props = defineProps({ + context: Object +}) +props.context.node.input(chosenItems) const getDataFromEndpoint = async () => { try { URIList.value = await getDatasetCategories(instance.api.baseUrl); + // Sortiere die URIList alphabetisch nach dem pref_label.de + URIList.value.sort((a, b) => { + return a.pref_label.de.localeCompare(b.pref_label.de); + }); } catch (error) { console.log(error); } } +const addTolist = (item) => { + + const itemExists = chosenItems.value.find(obj => obj.id === item.id); + + if (itemExists) { + // Entferne den Eintrag + chosenItems.value = chosenItems.value.filter(obj => obj.id !== item.id); + } else { + // Füge den Eintrag hinzu + chosenItems.value.push({ id: item.id, uri: item.resource, labels: item.pref_label }); + } + if (chosenItems.value.length > 1) { + chosenItems.value.find(obj => obj.isValid = true) + + } else chosenItems.value.find(obj => obj.isValid = false); + + props.context.node.input(chosenItems) +} onMounted(() => { getDataFromEndpoint(); + }); </script> @@ -70,7 +106,7 @@ onMounted(() => { gap: var(--Spacing-5, 32px); align-self: stretch; - + span { height: 51px; @@ -89,14 +125,28 @@ onMounted(() => { .dpiV3_findabilityThemesWrap { display: flex; - width: 471px; align-items: flex-start; align-content: flex-start; + width: 412px; /* gap: 8px var(--Spacing-2, 8px); */ + align-self: stretch; flex-wrap: wrap; } .chipBody { height: 0 !important } + +.dpiV3_errormsgWrapper { + width: 450px; + position: absolute; + right: 10px; + bottom: 104px; + color: var(--text-error, #A9242C); + + span { + color: var(--text-error, #A9242C); + text-align: right; + } +} </style> \ No newline at end of file diff --git a/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/HVDPage.vue b/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/HVDPage.vue index 26ad351b0edce7de139b3c580e47656bdd868898..d33ef7dda5bd66003a8b5fe6d3bda9c11348c1e1 100644 --- a/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/HVDPage.vue +++ b/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/HVDPage.vue @@ -12,11 +12,8 @@ <div class="dpiV3_Frame_830"> <div class="dpiV3_Switch"> <SwitchV3 - @switch-toggled="onSwitchToggled" - :hasIcon="false" - :defaultChecked="false" - :disabled="false" - /> + @switch-toggled="chosenItems[0].isValid === true ? onSwitchToggled(switchState) : (chosenItems[0].isValid = true, switchState = !switchState )" + :hasIcon="false" :defaultChecked="false" :disabled="false" /> </div> <div class="dpiV3_Switch_Label copy-large-semi-bold"> @@ -26,24 +23,22 @@ <div class="dpiV3_Sub_Info copy-large-regular"> {{ $t("message.dataupload.datasets.hvdPage.sub-info") }} </div> - <Dropdown - dropdownWidth="large" - :isDisabled="!switchState" - type="inputField" - :inputFieldProps="{ - isDisabled: !switchState, - addOnText: false, - initialHintText: false, - datePicker: false, - infoIcon: false, - preIcon: false, - label: 'HVD-Kategorie', - dropdown_dpiV3: true, - placeholder: 'Wählen Sie eine HVD-Kategorie', - inputFieldSize: 'large', - }" - :data="dropdownOptions" - /> + <Dropdown dropdownWidth="large" :isDisabled="!switchState" type="inputField" :inputFieldProps="{ + isDisabled: !switchState, + addOnText: false, + initialHintText: false, + datePicker: false, + infoIcon: false, + preIcon: false, + label: 'HVD-Kategorie', + dropdown_dpiV3: true, + placeholder: 'Wählen Sie eine HVD-Kategorie', + inputFieldSize: 'large', + }" :data="dropdownOptions" @click="handleClick($event)" /> + </div> + <div class="dpiV3_errormsgWrapper" v-if="chosenItems.find(obj => obj.isValid === false)"> + <PhWarning :size="16" weight="fill" /> + <span class="copy-mini-regular">Bitte wählen Sie eine HVD-Kategorie aus, bevor Sie fortfahren.</span> </div> </div> </div> @@ -57,6 +52,7 @@ import "../config/styles/variables.css"; import "../config/styles/typography.css"; import SwitchV3 from "../HappyFlowComponents/ui/SwitchV3.vue"; import Dropdown from "../HappyFlowComponents/ui/Dropdown.vue"; +import { PhWarning } from "@phosphor-icons/vue"; const { t } = useI18n(); @@ -65,12 +61,20 @@ const switchState = ref(false); const hvdCategories = ref([]); const error = ref(null); const dropdownTextArray = ref([]); +let chosenItems = ref([{ isValid: true }]) const onSwitchToggled = (state) => { - switchState.value = state; - console.log(switchState.value); + chosenItems.value[0].isValid = false; + switchState.value = !state; + console.log(switchState); }; +const props = defineProps({ + context: Object +}) + +props.context.node.input(chosenItems) + const dropdownOptions = computed(() => dropdownTextArray.value.map((text) => ({ "@value": text, @@ -78,6 +82,10 @@ const dropdownOptions = computed(() => })) ); +const handleClick = (e) => { + chosenItems.value[0].isValid = true; + +} const fetchHvdCategories = async () => { try { const instance = @@ -109,6 +117,7 @@ onMounted(() => { } .dpiV3_Frame_831 { + position: relative; display: flex; flex-direction: column; align-items: flex-start; @@ -153,4 +162,16 @@ onMounted(() => { .dpiV3_Sub_Info { color: var(--neutral-80, #3d4952); } + +.dpiV3_errormsgWrapper { + position: absolute; + right: 0; + bottom: -45px; + color: var(--text-error, #A9242C); + + span { + color: var(--text-error, #A9242C); + text-align: right; + } +} </style> diff --git a/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/PolGeoUriPage.vue b/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/PolGeoUriPage.vue index 94a557dd1ac00d71a54cb9a536069f0e2aca2a97..dfe005be85e4bdaab57bc4c887cb36b88bf9f884 100644 --- a/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/PolGeoUriPage.vue +++ b/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/PolGeoUriPage.vue @@ -14,9 +14,10 @@ placeholder: 'Geben Sie die geopolitische Abdeckung ein..', inputFieldSize: 'large', autocomplete: 'true', - }" :data="URIList" multi="true" :autocomplete="true" /> + }" @valueSent="handleValue" :data="URIList" multi="true" :autocomplete="true" /> </div> + </div> </template> <script setup> @@ -25,12 +26,19 @@ import Dropdown from "../HappyFlowComponents/ui/Dropdown.vue"; import { filterGeocodingURIs } from "../HappyFlowComponents/services/dpiV3_apis"; import { ref } from 'vue'; import { getCurrentInstance } from "vue"; +import { isValid } from "zod"; let URIList = ref([]); let instance = getCurrentInstance().appContext.app.config.globalProperties.$env; let debounceTimer; +const props = defineProps({ + context: Object, +}); +// Optional, deswegen valid +props.context.node.input([{ 'isValid': true}]) + const filterVocabularies = async (e) => { clearTimeout(debounceTimer); // Lösche den vorherigen Timer @@ -47,6 +55,9 @@ const filterVocabularies = async (e) => { }, 500); // Warte 500 ms nach der letzten Eingabe } +const handleValue = (item) => { + props.context.node.input([{ 'isValid': true, 'uri': item.resource, 'id': item.id }]) +} </script> <style scoped> .dpiV3_dropdownWrapper { diff --git a/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/PublisherPage.vue b/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/PublisherPage.vue index a88947e43b586018b96e7fbb897dbabc0a819c22..27f8a3522c3dbabb1caece6733d512ccfcce0c73 100644 --- a/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/PublisherPage.vue +++ b/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/PublisherPage.vue @@ -8,8 +8,8 @@ <div> <span class="copy-small-semi-bold">Konto</span> </div> - <TextButtonSmall buttonText="Diese Details verwenden" iconStart="true" - iconName="copy"></TextButtonSmall> + <TextButtonSmall buttonText="Diese Details verwenden" iconStart="true" iconName="copy"> + </TextButtonSmall> </div> <div class="secondRow"> <span class="copy-small-regular" v-for="item in testdata"> @@ -17,19 +17,26 @@ </span> </div> </div> - <InputField @input="handleInput($event, 'foaf:name')" :addOnText="false" :datePicker="false" :infoIcon="false" - :placeholder="$t('message.dataupload.datasets.dct:publisher.nameInput.placeholder')" :preIcon="false" - inputFieldSize="large" :initialHintText="false" - :label="$t('message.dataupload.datasets.dct:publisher.nameInput.title')" :showEndIcon="false" /> - <InputField @input="handleInput($event, 'foaf:mbox')" :addOnText="false" :datePicker="false" :infoIcon="false" - :placeholder="$t('message.dataupload.datasets.dct:publisher.mailInput.placeholder')" :preIcon="false" - inputFieldSize="large" :initialHintText="false" + <InputField @input="handleInput($event, 'foaf:name', 1)" :addOnText="false" :datePicker="false" + :infoIcon="false" :placeholder="$t('message.dataupload.datasets.dct:publisher.nameInput.placeholder')" + :preIcon="false" inputFieldSize="large" :initialHintText="false" + :label="$t('message.dataupload.datasets.dct:publisher.nameInput.title')" :showEndIcon="false" + :showError="arr[0].isValid === false && validInputs[1] === false" /> + <InputField @input="handleInput($event, 'foaf:mbox', 2)" :addOnText="false" :datePicker="false" + :infoIcon="false" :placeholder="$t('message.dataupload.datasets.dct:publisher.mailInput.placeholder')" + :preIcon="false" inputFieldSize="large" :initialHintText="false" + :showError="arr[0].isValid === false && validInputs[2] === false" :label="$t('message.dataupload.datasets.dct:publisher.mailInput.title')" :showEndIcon="false" /> - <InputField @input="handleInput($event, 'foaf:homepage')" :addOnText="true" :datePicker="false" + <InputField @input="handleInput($event, 'foaf:homepage', 3)" :addOnText="true" :datePicker="false" :infoIcon="false" :placeholder="$t('message.dataupload.datasets.dct:publisher.websiteInput.placeholder')" :preIcon="false" inputFieldSize="large" :initialHintText="false" addOnLeadingText="https://" - :label="$t('message.dataupload.datasets.dct:publisher.websiteInput.title')" :showEndIcon="false" /> + :label="$t('message.dataupload.datasets.dct:publisher.websiteInput.title')" :showEndIcon="false" + :showError="arr[0].isValid === false && validInputs[3] === false" /> <div> {{ $t("message.dataupload.datasets.dct:publisher.descriptionBottom") }}</div> + <div class="dpiV3_errormsgWrapper" v-if="arr.find(obj => obj.isValid === false)"> + <PhWarning :size="16" weight="fill" /> + <span class="copy-mini-regular">Bitte füllen Sie alle Pflichtfelder aus, bevor Sie fortfahren.</span> + </div> </div> </template> @@ -37,18 +44,29 @@ import { ref } from 'vue'; import InputField from "../HappyFlowComponents/ui/InputField.vue"; import TextButtonSmall from "../HappyFlowComponents/ui/TextButtonSmall.vue"; +import { PhWarning } from "@phosphor-icons/vue"; const props = defineProps({ context: Object }); - +let validInputs = ref({ 1: false, 2: false, 3: false }) const testdata = ['Mobilitätsreferat der Landeshauptstadt München', 'contact@example.com', 'https://example.com'] const arr = ref([ - { "foaf:name": "" }, - { "foaf:mbox": "" }, - { "foaf:homepage": "" } + { isValid: 'unset', "foaf:name": "", "foaf:mbox": "", "foaf:homepage": "" }, ]); +props.context.node.input(arr) +const handleInput = (e, namespace, iIndex) => { + if (e.target.value != "") { + validInputs.value[iIndex] = true + if (validInputs.value[1] && validInputs.value[2] && validInputs.value[3]) { + arr.value[0].isValid = true + } + } else { + validInputs.value[iIndex] = false + if (!validInputs.value[1] || !validInputs.value[2] || !validInputs.value[3]) { + arr.value[0].isValid = false + } + } -const handleInput = (e, namespace) => { const newValue = e.target.value; // Aktualisiere nur den Wert des entsprechenden Namensraums arr.value = arr.value.map(item => { @@ -100,9 +118,23 @@ const handleInput = (e, namespace) => { align-items: flex-start; gap: var(--Spacing-1, 4px); align-self: stretch; - span{ + + span { color: var(--neutral-80, #3D4952); } } } + +.dpiV3_errormsgWrapper { + width: 375px; + position: absolute; + right: 10px; + bottom: 104px; + color: var(--text-error, #A9242C); + + span { + color: var(--text-error, #A9242C); + text-align: right; + } +} </style> \ No newline at end of file diff --git a/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/TempResPage.vue b/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/TempResPage.vue index b1a9e63c752a94f8cc19939243b9d4f91969684d..e422390a64b2443cddaab59f49c3e5286d66f29d 100644 --- a/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/TempResPage.vue +++ b/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/TempResPage.vue @@ -6,9 +6,9 @@ <div class="dpiV3_firstRow"> <div class="dpiV3_firstRow_inner"> <InputField @input="handleInput($event.target.value, index, 'dcat:startDate')" :defaultInput="true" - :addOnText="false" :eraseable="false" :datePicker="true" :infoIcon="false" - placeholder="TT/MM/JJJJ" label="Aktualisierungsdatum" :preIcon="false" inputFieldSize="large" - :initialHintText="false" :showEndIcon="false" inputType="date"></InputField> + :addOnText="false" :eraseable="false" :datePicker="true" :infoIcon="false" value="TT/MM/JJJJ" + label="Aktualisierungsdatum" :preIcon="false" inputFieldSize="large" :initialHintText="false" + :showEndIcon="false" inputType="date"></InputField> <InputField v-show="checkboxState[index]" @input="handleInput($event.target.value, index, 'startTime')" :defaultInput="true" :addOnText="false" :eraseable="false" :timePicker="true" inputType="time" :infoIcon="false" @@ -18,9 +18,9 @@ </div> <div class="dpiV3_firstRow_inner"> <InputField @input="handleInput($event.target.value, index, 'dcat:endDate')" :defaultInput="true" - :addOnText="false" :eraseable="false" :datePicker="true" :infoIcon="false" - placeholder="TT/MM/JJJJ" label="Aktualisierungsdatum" :preIcon="false" inputFieldSize="large" - :initialHintText="false" :showEndIcon="false" inputType="date"></InputField> + :addOnText="false" :eraseable="false" :datePicker="true" :infoIcon="false" value="TT/MM/JJJJ" + label="Aktualisierungsdatum" :preIcon="false" inputFieldSize="large" :initialHintText="false" + :showEndIcon="false" inputType="date"></InputField> <InputField v-show="checkboxState[index]" @input="handleInput($event.target.value, index, 'endTime')" :defaultInput="true" :addOnText="false" :eraseable="false" :timePicker="true" inputType="time" :infoIcon="false" @@ -42,7 +42,7 @@ <div class="dpiV3_tempAddMore"> <ButtonV3 :buttonText='$t("message.dataupload.datasets.dcat:temporalResolution.addMore")' size="medium" iconStart="plus" variant="tertiary" - @click=" timesList.push({ id: timesList.length + 1 }); dynamicButtonText = t('message.dataupload.menu.delete')" /> + @click="timesList.push({ id: timesList.length + 1 }); dynamicButtonText = t('message.dataupload.menu.delete'); initNewIndex()" /> </div> </div> @@ -61,17 +61,51 @@ let timesList = ref([{ id: 0, 'dcat:startDate': "DD/MM/YYYY", 'dcat:endDate': "D const currentIndex = ref() let dynamicButtonText = ref(t("message.dataupload.menu.reset")) +const props = defineProps({ + context: Object, +}); + +const arr = ref([ + { isValid: true, type: 'dct:PeriodOfTime', "dct:temporal": [{ dataType: 'date', 'dcat:startDate': '', 'dcat:endDate': '' }] }, +]); +props.context.node.input([{ 'isValid': true}]) +// props.context.node.input(arr) // Watcher für dynamische Aktualisierung watch(() => t("message.dataupload.menu.reset"), (newText) => { dynamicButtonText.value = newText; }); +const initNewIndex = () => { + // Liste cachen und Indizes hinzufügen + let cacheList = arr.value[0]['dct:temporal'] + cacheList.push({ dataType: 'date', 'dcat:startDate': '', 'dcat:endDate': '' }) + arr.value[0]['dct:temporal'] = cacheList + props.context.node.input(arr) +} + const handleCheckboxChange = (event, i) => { - const checked = event.target.checked; // Extrahiere den checked-Wert + // Extrahiere den checked-Wert + const checked = event.target.checked; checkboxState.value[i] = checked; + + if (checkboxState.value[i]) { + arr.value[0]['dct:temporal'][i]['dataType'] = 'dateTime' + } else arr.value[0]['dct:temporal'][i]['dataType'] = 'date' + } const handleInput = (dateItem, index, key) => { - // ToDo + + // Muss sicherstellen, dass Zeiten an die Properties geschrieben werden + if (key === 'endTime' || key === 'startTime') { + if (key === 'endTime') { + arr.value[0]['dct:temporal'][index]['dcat:endDate'] = arr.value[0]['dct:temporal'][index]['dcat:endDate'] + 'T' + dateItem + } + if (key === 'startTime') { + arr.value[0]['dct:temporal'][index]['dcat:startDate'] = arr.value[0]['dct:temporal'][index]['dcat:startDate'] + 'T' + dateItem + } + } + else arr.value[0]['dct:temporal'][index][key] = dateItem + props.context.node.input(arr) } const removeIndex = (index) => { // Verwende die ID des Objekts, um es zu entfernen diff --git a/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/TitelPage.vue b/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/TitelPage.vue index 78ec55192867a0654c8b2616a36de3549350fd6e..86756ca5820881fc98f2feaa3d431059569c17ec 100644 --- a/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/TitelPage.vue +++ b/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/TitelPage.vue @@ -1,41 +1,42 @@ <template> - <div class="V3-typography dpiV3_Frame_3841"> - <h4> - {{ $t("message.dataupload.datasets.dct:title.title") }} - </h4> - <div class="copy-large-regular"> - {{ $t("message.dataupload.datasets.dct:title.description") }} - </div> - - <InputField - @input="handleInput" - :addOnText="false" - :datePicker="false" - :infoIcon="false" - placeholder="Geben Sie Ihrem Datensatz einen Titel..." - :preIcon="false" - :initialHintText="false" - label="Titel" - :showEndIcon="false" - ></InputField> + <div class="V3-typography dpiV3_Frame_3841"> + <h4> + {{ $t("message.dataupload.datasets.dct:title.title") }} + </h4> + <div class="copy-large-regular"> + {{ $t("message.dataupload.datasets.dct:title.description") }} + </div> + <InputField @input="handleInput" :addOnText="false" :datePicker="false" :infoIcon="false" + placeholder="Geben Sie Ihrem Datensatz einen Titel..." :preIcon="false" :initialHintText="false" label="Titel" + :showEndIcon="false" :showError="chosenItems[0].isValid === false"></InputField> + <div class="dpiV3_errormsgWrapper" v-if="chosenItems.find(obj => obj.isValid === false)"> + <PhWarning :size="16" weight="fill" /> + <span class="copy-mini-regular">Bitte geben Sie einen Titel ein, bevor Sie fortfahren.</span> </div> + </div> </template> <script setup> import { useI18n } from "vue-i18n"; import "../config/styles/variables.css"; import "../config/styles/typography.css"; -import { ref, onMounted, getCurrentInstance, computed } from "vue"; +import { ref } from "vue"; import InputField from "../HappyFlowComponents/ui/InputField.vue"; +import { PhWarning } from "@phosphor-icons/vue"; const { t } = useI18n(); const props = defineProps({ context: Object, }); - +let chosenItems = ref([{ isValid: 'unset' , 'dct:title': '' }]) +props.context.node.input(chosenItems) const handleInput = (e) => { - props.context.node.input(e.target.value); + + if (e.target.value != '') { + chosenItems.value[0].isValid = true + } else chosenItems.value[0].isValid = false + chosenItems.value[0]['dct:title'] = e.target.value }; </script> @@ -60,4 +61,17 @@ const handleInput = (e) => { align-self: stretch; color: var(--neutral-80, #3d4952); } + +.dpiV3_errormsgWrapper { + width: 350px; + position: absolute; + right: 10px; + bottom: 104px; + color: var(--text-error, #A9242C); + + span { + color: var(--text-error, #A9242C); + text-align: right; + } +} </style> diff --git a/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/UpdateDate.vue b/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/UpdateDate.vue index 5c6e18de93f59675d4dd355f411867b67a7fff61..7e5b1608f8b32252a64bed0baeb1149d6020df75 100644 --- a/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/UpdateDate.vue +++ b/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/UpdateDate.vue @@ -21,22 +21,46 @@ :initialHintText="false" :showEndIcon="false" inputType="date" + :showError="chosenItems[0].isValid === false" ></InputField> + <div class="dpiV3_errormsgWrapper" v-if="chosenItems.find(obj => obj.isValid === false)"> + <PhWarning :size="16" weight="fill" /> + <span class="copy-mini-regular">Bitte geben Sie ein Aktualisierungsdatum ein, bevor Sie fortfahren.</span> + </div> </div> </div> </template> <script setup> +import { PhWarning } from "@phosphor-icons/vue"; +import { ref } from "vue"; import InputField from "../HappyFlowComponents/ui/InputField.vue"; const props = defineProps({ context: Object, }); - +let chosenItems = ref([{ isValid: 'unset' }]) +props.context.node.input(chosenItems) const handleInput = (e) => { - props.context.node.input(e.target.value); + + if (e.target.value != '') { + chosenItems.value[0].isValid = true + } else chosenItems.value[0].isValid = false + chosenItems.value[0]['dct:modified'] = e.target.value }; </script> <style scoped> +.dpiV3_errormsgWrapper { + width: 435px; + position: absolute; + right: 10px; + bottom: 104px; + color: var(--text-error, #A9242C); + + span { + color: var(--text-error, #A9242C); + text-align: right; + } +} </style> diff --git a/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/dpiV3Description.vue b/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/dpiV3Description.vue index a53cafbabd054a6f5ac3cdd765f7de01303698e8..8368200458536fc190199597f7145b4152d31ac3 100644 --- a/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/dpiV3Description.vue +++ b/packages/piveau-hub-ui-modules/lib/data-provider-interface/components/dpiV3Description.vue @@ -2,19 +2,31 @@ <div class="dpiV3InnerComponentWrap"> <h4>{{ $t("message.dataupload.datasets.dct:description.title") }}</h4> <div> {{ $t("message.dataupload.datasets.dct:description.description") }}</div> - <TextAreaV3 @input="handleInput" class="dpiV3_input-field" :hint="false" :label='$t("message.dataupload.datasets.dct:description.input.title")' :placeholder='$t("message.dataupload.datasets.dct:description.input.placeholder")'></TextAreaV3> + <TextAreaV3 @input="handleInput" class="dpiV3_input-field" :hint="false" + :label='$t("message.dataupload.datasets.dct:description.input.title")' + :placeholder='$t("message.dataupload.datasets.dct:description.input.placeholder")' :showError="chosenItems[0].isValid === false"></TextAreaV3> + <div class="dpiV3_errormsgWrapper" v-if="chosenItems.find(obj => obj.isValid === false)"> + <PhWarning :size="16" weight="fill" /> + <span class="copy-mini-regular">Bitte geben Sie einen Titel ein, bevor Sie fortfahren.</span> + </div> </div> </template> <script setup> import TextAreaV3 from "../HappyFlowComponents/ui/TextAreaV3.vue"; +import { PhWarning } from "@phosphor-icons/vue"; +import { ref} from "vue"; const props = defineProps({ context: Object }) - +let chosenItems = ref([{ isValid: 'unset', 'dct:description': '' }]) const handleInput = (e) => { - props.context.node.input(e.target.value) + if (e.target.value != '') { + chosenItems.value[0].isValid = true + } else chosenItems.value[0].isValid = false + chosenItems.value[0]['dct:description'] = e.target.value } +props.context.node.input(chosenItems) </script> <style scoped> .formkit-input { @@ -29,4 +41,16 @@ const handleInput = (e) => { align-self: stretch; width: unset; } +.dpiV3_errormsgWrapper { + width: 350px; + position: absolute; + right: 10px; + bottom: 104px; + color: var(--text-error, #A9242C); + + span { + color: var(--text-error, #A9242C); + text-align: right; + } +} </style> \ No newline at end of file diff --git a/packages/piveau-hub-ui-modules/lib/data-provider-interface/views/InputPage.vue b/packages/piveau-hub-ui-modules/lib/data-provider-interface/views/InputPage.vue index b9b65554d8e850f56ba6c2b1451de3796689b8f8..79c08ca2faf5b1f326f2434d816e70287a7a088b 100644 --- a/packages/piveau-hub-ui-modules/lib/data-provider-interface/views/InputPage.vue +++ b/packages/piveau-hub-ui-modules/lib/data-provider-interface/views/InputPage.vue @@ -2,11 +2,11 @@ <div class="form-container V3-typography"> <div ref="fkInputContainer" class="inputContainer" v-if="isInput"> <div class="formContainer formkit position-relative"> - <!-- <details>{{ formValues }}</details> --> + <details>{{ formValues }}</details> <FormKit type="form" v-model="formValues" :actions="false" :plugins="[stepPlugin]" id="dpiForm" @change="saveFormValues({ property: property, page: page, distid: id, values: formValues })" @click="saveFormValues({ property: property, page: page, distid: id, values: formValues })" @submit.prevent="" - class="d-flex" > + class="d-flex"> <!-- DpiV3 Stepper - make it a component! --> @@ -125,7 +125,8 @@ In this new approach, every property out of the page-content-config.js gets loaded separately. This is for the substepper to work correctly --> - <div style="width: 100%" v-for="(item, innerIndex) in Object.keys(getSchema(property).value[stepName]).length" + <div style="width: 100%" + v-for="(item, innerIndex) in Object.keys(getSchema(property).value[stepName]).length" v-show="Object.values(getSchema(property).value[stepName][innerIndex])[0] === activeSubStep.replace(/_\d+$/, '') || stepName === 'Landing'"> <FormKitSchema v-if="stepName !== 'Distributions'" @handleNav="handleNavInput" :schema="getSchema(property).value[stepName][innerIndex]" :library="library"> @@ -142,7 +143,10 @@ <div class="dpiV3_CTANav"> <ButtonV3 iconStart="CaretLeft" v-if="activeStep !== 'Landing'" buttonText="Zurück" size="large" @click="navTrigger('prev')" variant="secondary" /> - <ButtonV3 iconEnd="CaretRight" buttonText="Weiter" size="large" @click="navTrigger('next')" /> + + <ButtonV3 iconEnd="CaretRight" buttonText="Weiter" size="large" + @click="formValues[activeStep][activeSubStep][0].isValid === true ? navTrigger('next') : formValues[activeStep][activeSubStep][0].isValid = false" /> + </div> </div> <div class="dpiV3_Content_InputPage" v-if="activeSubStep.includes('hvdPage')"> @@ -290,12 +294,17 @@ import "../config/styles/typography.css"; import { PhCheckCircle, PhNumberCircleFive } from "@phosphor-icons/vue"; import { plugin, defaultConfig } from '@formkit/vue' import { useDpiContext, useFormSchema } from '../composables'; +import { getNode } from '@formkit/core' + export default defineComponent({ props: { property: { required: true, type: String, + }, + context: { + }, id: { type: String, @@ -384,6 +393,7 @@ export default defineComponent({ ); }, }, + methods: { ...mapActions('auth', [ 'setIsEditMode', @@ -417,64 +427,73 @@ export default defineComponent({ } }, navTrigger(value, i) { - let steplist = []; - Object.keys(this.steps).forEach((key, index) => { - let item = { - step: key, - substeps: this.subSteps[index], - substepCount: Object.keys(this.subSteps[index]).length, - }; - steplist.push(item); - }); - if (value === "next") { - if (steplist[this.stepCounter]["substepCount"] > 1) { - if ( - this.substepCounter + 1 === - steplist[this.stepCounter]["substepCount"] - ) { - this.stepCounter++; - this.activeStep = steplist[this.stepCounter]["step"]; - this.activeSubStep = Object.keys( - steplist[this.stepCounter]["substeps"] - )[0]; - this.substepCounter = 0; + try { + + + // Check if step is valid + let steplist = []; + Object.keys(this.steps).forEach((key, index) => { + let item = { + step: key, + substeps: this.subSteps[index], + substepCount: Object.keys(this.subSteps[index]).length, + }; + steplist.push(item); + }); + if (value === "next") { + if (steplist[this.stepCounter]["substepCount"] > 1) { + if ( + this.substepCounter + 1 === + steplist[this.stepCounter]["substepCount"] + ) { + this.stepCounter++; + this.activeStep = steplist[this.stepCounter]["step"]; + this.activeSubStep = Object.keys( + steplist[this.stepCounter]["substeps"] + )[0]; + this.substepCounter = 0; + } else { + this.substepCounter++; + this.activeSubStep = Object.keys( + steplist[this.stepCounter]["substeps"] + )[this.substepCounter]; + } } else { - this.substepCounter++; - this.activeSubStep = Object.keys( - steplist[this.stepCounter]["substeps"] - )[this.substepCounter]; - } - } else { - if (this.stepCounter != steplist.length - 1) { - this.stepCounter++; - this.activeSubStep = Object.keys(steplist[this.stepCounter]["substeps"])[0]; - this.activeStep = steplist[this.stepCounter]["step"]; + if (this.stepCounter != steplist.length - 1) { + this.stepCounter++; + this.activeSubStep = Object.keys(steplist[this.stepCounter]["substeps"])[0]; + this.activeStep = steplist[this.stepCounter]["step"]; + } } } - } - if (value === "prev") { - if (steplist[this.stepCounter]["substepCount"] > 1) { - - if (this.substepCounter > 0) { - this.substepCounter--; - this.activeSubStep = Object.keys( - steplist[this.stepCounter]["substeps"] - )[this.substepCounter]; + if (value === "prev") { + if (steplist[this.stepCounter]["substepCount"] > 1) { + + if (this.substepCounter > 0) { + this.substepCounter--; + this.activeSubStep = Object.keys( + steplist[this.stepCounter]["substeps"] + )[this.substepCounter]; + } else { + this.stepCounter--; + this.activeStep = steplist[this.stepCounter]["step"]; + this.substepCounter = + Object.keys(steplist[this.stepCounter]["substeps"]).length - 1; + this.activeSubStep = Object.keys( + steplist[this.stepCounter]["substeps"] + )[this.substepCounter]; + } } else { + this.substepCounter = Object.keys(steplist[this.stepCounter - 1]["substeps"]).length - 1; this.stepCounter--; + this.activeSubStep = Object.keys(steplist[this.stepCounter]["substeps"])[this.substepCounter]; this.activeStep = steplist[this.stepCounter]["step"]; - this.substepCounter = - Object.keys(steplist[this.stepCounter]["substeps"]).length - 1; - this.activeSubStep = Object.keys( - steplist[this.stepCounter]["substeps"] - )[this.substepCounter]; } - } else { - this.substepCounter = Object.keys(steplist[this.stepCounter - 1]["substeps"]).length - 1; - this.stepCounter--; - this.activeSubStep = Object.keys(steplist[this.stepCounter]["substeps"])[this.substepCounter]; - this.activeStep = steplist[this.stepCounter]["step"]; } + + } catch (error) { + console.log(error); + } }, dropdownCLick() { @@ -513,11 +532,11 @@ export default defineComponent({ initialSchema[key].map((el) => el.name).includes("dct:modified") ); - - + + this.$formkit.setLocale('de'); // console.log(this.$formkit); - + // this.$formkit.getValidationMessages() if (localStorage.getItem('dpi_editmode') === 'true' && stepWithDates != undefined) { @@ -901,6 +920,7 @@ export default defineComponent({ .dpiV3_substepText { color: var(--neutral-60, #687178); } + .formerlyVisitedStep { color: var(--neutral-80, #3D4952); } @@ -1039,7 +1059,7 @@ export default defineComponent({ justify-content: space-between; align-items: center; align-self: stretch; - margin-top: var(--Spacing-6, 48px); + margin-top: var(--Spacing-8, 64px); // padding: var(--Spacing-5, 32px) var(--Spacing-6, 48px); } @@ -1595,7 +1615,8 @@ select { rotate: 45deg !important; } } -.dpiV3_seperatorHorizontalStepperInnerVisited{ + +.dpiV3_seperatorHorizontalStepperInnerVisited { background: var(--neutral-60, #687178); } </style> diff --git a/packages/piveau-hub-ui-modules/lib/scss/_dpi-style.scss b/packages/piveau-hub-ui-modules/lib/scss/_dpi-style.scss index c8e222e7f1ea6c7b9d89f9217930e068d298eaea..7434fadbbf89153e0ac29de346db8080df70bf4c 100644 --- a/packages/piveau-hub-ui-modules/lib/scss/_dpi-style.scss +++ b/packages/piveau-hub-ui-modules/lib/scss/_dpi-style.scss @@ -1458,7 +1458,7 @@ } .activeSection { - + position: relative; // width: 100%; // padding: 0 1rem; // margin: 1rem 0; @@ -1468,6 +1468,7 @@ } + .repeatable { display: flex; flex-direction: column; @@ -1624,6 +1625,7 @@ gap: var(--Spacing-5, 32px); align-self: stretch; } + .dpiV3AutoCompleteWrap { display: flex; min-width: 416px; @@ -1633,36 +1635,37 @@ align-items: flex-start; gap: var(--Spacing-3, 16px); align-self: stretch; - + border-radius: var(--Modal-Radius, 32px); background: var(--blue-10, #f3fbff); - + .firstRow { - div { + div { + display: flex; + align-items: center; + gap: var(--Spacing-3, 16px); + + } + + .icon_title { + color: var(--neutral-80, #3d4952); + } + display: flex; align-items: center; - gap: var(--Spacing-3, 16px); - - } - - .icon_title { - color: var(--neutral-80, #3d4952); - } - - display: flex; - align-items: center; - gap: 16px; - - } - + gap: 16px; + + } + .secondRow { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: var(--Spacing-1, 4px); - align-self: stretch; - span { - color: var(--neutral-80, #3d4952); - } - } - } \ No newline at end of file + display: flex; + flex-direction: column; + align-items: flex-start; + gap: var(--Spacing-1, 4px); + align-self: stretch; + + span { + color: var(--neutral-80, #3d4952); + } + } +} \ No newline at end of file