Align folders with documents in document tool

* Change buttons to the new BaseButton component inside document list
* Create DocumentEntry component to show the icon of a document entry,
depending on the type of entry (folder, file) it will show icons
appropriately
* Change name of resourceFileIcon to resource file to accommodate
folder icons
* Add small size to base button and icon
* Change case in tailwind config for consistency
pull/4715/head
Daniel Gayoso González 2 years ago
parent 641d4cae65
commit c513b8a6ea
  1. 60
      assets/vue/components/basecomponents/BaseButton.vue
  2. 26
      assets/vue/components/basecomponents/BaseIcon.vue
  3. 19
      assets/vue/components/basecomponents/ChamiloIcons.js
  4. 49
      assets/vue/components/documents/DocumentEntry.vue
  5. 36
      assets/vue/components/documents/ResourceFileIcon.vue
  6. 6
      assets/vue/components/documents/ResourceFileLink.vue
  7. 33
      assets/vue/components/documents/ResourceIcon.vue
  8. 4
      assets/vue/views/course/Home.vue
  9. 4
      assets/vue/views/documents/DocumentForHtmlEditor.vue
  10. 64
      assets/vue/views/documents/List.vue
  11. 4
      assets/vue/views/documents/ListQuasar.vue
  12. 4
      assets/vue/views/personalfile/List.vue
  13. 4
      assets/vue/views/personalfile/Shared.vue
  14. 4
      assets/vue/views/usergroup/List.vue
  15. 1
      assets/vue/views/userreluser/List.vue
  16. 4
      tailwind.config.js

@ -6,12 +6,12 @@
:class="buttonClass"
:outlined="primeOutlinedProperty"
:text="primeTextProperty"
:severity="primeSeverityProperty"
:size="size"
@click="$emit('click', $event)"
>
<BaseIcon class="text-inherit" :icon="icon"/>
<BaseIcon class="text-inherit" :icon="icon" :size="size" />
<span
v-if="!props.onlyIcon"
v-if="!onlyIcon && label"
class="hidden md:block text-inherit"
>
{{ label }}
@ -45,9 +45,14 @@ const props = defineProps({
required: true,
validator: (value) => {
if (typeof (value) !== "string") {
return false
return false;
}
return ["primary", "secondary", "black"].includes(value);
return [
"primary",
"secondary",
"black",
"danger",
].includes(value);
}
},
// associate this button to a popup through its identifier, this will make this button toggle the popup
@ -58,7 +63,20 @@ const props = defineProps({
onlyIcon: {
type: Boolean,
default: false,
}
},
size: {
type: String,
default: "normal",
validator: (value) => {
if (typeof (value) !== "string") {
return false
}
return [
"normal",
"small",
].includes(value);
}
},
});
defineEmits(["click"]);
@ -67,14 +85,23 @@ const buttonClass = computed(() => {
if (props.onlyIcon) {
return "p-3";
}
let result = "py-2.5 px-4 ";
let result =""
switch (props.size) {
case "normal":
result += "py-2.5 px-4 ";
break;
case "small":
result += "py-2 px-3.5 "
}
switch (props.type) {
case "primary":
result += "border-primary hover:bg-primary text-primary hover:text-white";
result += "border-primary hover:bg-primary text-primary hover:text-white ";
break;
case "secondary":
result += "bg-secondary hover:bg-secondary-gradient text-white";
result += "bg-secondary hover:bg-secondary-gradient text-white ";
break;
case "danger":
result += "border-error hover:bg-error text-error hover:text-white ";
}
return result;
});
@ -86,7 +113,7 @@ const primeOutlinedProperty = computed(() => {
}
switch (props.type) {
case "primary":
return true;
case "danger":
case "black":
return true;
default:
@ -98,17 +125,4 @@ const primeOutlinedProperty = computed(() => {
const primeTextProperty = computed(() => {
return props.onlyIcon;
});
// https://primevue.org/button/#severity primary and secondary modified by chamilo
const primeSeverityProperty = computed(() => {
if (props.onlyIcon) {
return "primary";
}
switch (props.type) {
case "secondary":
return "danger";
default:
return "primary";
}
});
</script>

@ -1,5 +1,5 @@
<template>
<i class="text-xl/4" :class="iconClass"/>
<i :class="iconClass"/>
</template>
<script setup>
@ -18,9 +18,31 @@ const props = defineProps({
return Object.keys(chamiloIconToClass).includes(value)
}
},
size: {
type: String,
default: "normal",
validator: (value) => {
if (typeof (value) !== "string") {
return false
}
return [
"normal",
"small",
].includes(value);
}
}
});
const iconClass = computed(() => {
return chamiloIconToClass[props.icon];
let iconClass = chamiloIconToClass[props.icon] + " ";
switch (props.size) {
case "normal":
iconClass += "text-xl/4 ";
break;
case "small":
iconClass += "text-base/4 ";
break;
}
return iconClass;
});
</script>

@ -5,8 +5,8 @@
* to the classes needed for represent every icon
*/
export const chamiloIconToClass = {
"pencil": "mdi mdi-pencil",
"delete": "",
"edit": "mdi mdi-pencil",
"delete": "mdi mdi-delete",
"hammer-wrench": "",
"download": "",
"download-box": "",
@ -21,13 +21,11 @@ export const chamiloIconToClass = {
"arrow-right-bold": "",
"magnify-plus-outline": "",
"archive-arrow-up": "",
"folder-multiple-plus": "",
"folder-plus": "",
"alert": "",
"checkbox-marked": "",
"pencil-off": "",
"eye": "mdi mdi-eye",
"eye-off": "",
"eye-on": "mdi mdi-eye",
"eye-off": "mdi mdi-eye-off",
"checkbox-multiple-blank": "",
"checkbox-multiple-blank-outline": "",
"sync": "",
@ -48,8 +46,15 @@ export const chamiloIconToClass = {
"file-plus": "",
"cloud-upload": "",
"dots-vertical": "",
"information": "",
"information": "mdi mdi-information",
"account-key": "",
"cog": "mdi mdi-cog",
"plus": "mdi mdi-plus",
"file-generic": "mdi mdi-file",
"file-image": "mdi mdi-file-image",
"file-video": "mdi mdi-file-video",
"file-pdf": "mdi mdi-file-pdf-box",
"folder-generic": "mdi mdi-folder",
"folder-multiple-plus": "mdi mdi-folder-multiple-plus",
"folder-plus": "mdi mdi-folder-plus",
};

@ -0,0 +1,49 @@
<template>
<div v-if="data && data.resourceNode && data.resourceNode.resourceFile">
<a
data-fancybox="gallery"
class="flex align-center"
:href="data.contentUrl"
:data-type="dataType"
>
<ResourceIcon class="mr-2" :file-type="data.filetype" />
{{ data.title }}
</a>
</div>
<div v-else>
<RouterLink
class="flex align-center"
:to="{
name: 'DocumentsList',
params: { node: data.resourceNode.id },
query: folderParams,
}"
>
<ResourceIcon class="mr-2" file-type="folder"/>
<b>{{ data.resourceNode.title }}</b>
</RouterLink>
</div>
</template>
<script setup>
import ResourceIcon from "./ResourceIcon.vue";
import {computed} from "vue";
const props = defineProps({
data: {
type: Object,
required: true,
},
});
const dataType = computed(() => {
if (props.data.resourceNode.resourceFile.image) {
return 'image';
}
if (props.data.resourceNode.resourceFile.video) {
return 'video';
}
return 'iframe';
});
</script>

@ -1,36 +0,0 @@
<template>
<span>
<v-icon
v-if="file.image"
icon="mdi-file-image"
medium
/>
<v-icon
v-else-if="file.video"
icon="mdi-file-video"
medium
/>
<v-icon
v-else-if="'application/pdf' === file.mimeType"
icon="mdi-file-pdf-box"
medium
/>
<v-icon
v-else
icon="mdi-file"
medium
/>
</span>
</template>
<script>
export default {
name: 'ResourceFileIcon',
props: {
file: Object
},
};
</script>

@ -4,17 +4,17 @@
:href="resource.contentUrl"
:data-type="getDataType"
>
<ResourceFileIcon :file="resource.resourceNode.resourceFile" />
<ResourceIcon :file="resource.resourceNode.resourceFile" />
{{ resource.title }}
</a>
</template>
<script>
import ResourceFileIcon from './ResourceFileIcon.vue';
import ResourceIcon from './ResourceIcon.vue';
export default {
name: 'ResourceFileLink',
components: {
ResourceFileIcon
ResourceIcon
},
computed: {
getDataType() {

@ -0,0 +1,33 @@
<template>
<BaseIcon
v-if="fileType === 'image'"
icon="file-image"
/>
<BaseIcon
v-else-if="fileType === 'video'"
icon="file-video"
/>
<BaseIcon
v-else-if="fileType === 'folder'"
icon="folder-generic"
/>
<BaseIcon
v-else-if="'application/pdf' === fileType.mimeType"
icon="file-pdf"
/>
<BaseIcon
v-else
icon="file-generic"
/>
</template>
<script setup>
import BaseIcon from "../basecomponents/BaseIcon.vue";
defineProps({
fileType: {
type: Object,
required: true,
},
});
</script>

@ -86,14 +86,14 @@
v-if="course && isCurrentTeacher"
type="black"
:label="t('See as student')"
icon="eye"
icon="eye-on"
/>
<BaseButton
v-if="showUpdateIntroductionButton"
type="black"
:label="t('Edit introduction')"
icon="pencil"
icon="edit"
@click="updateIntro(intro)"
/>

@ -103,7 +103,7 @@ import { mapFields } from 'vuex-map-fields';
import ListMixin from '../../mixins/ListMixin';
import ActionCell from '../../components/ActionCell.vue';
//import Toolbar from '../../components/Toolbar.vue';
import ResourceFileIcon from '../../components/documents/ResourceFileIcon.vue';
import ResourceIcon from '../../components/documents/ResourceIcon.vue';
import ResourceFileLink from '../../components/documents/ResourceFileLink.vue';
import { useRoute } from 'vue-router'
@ -121,7 +121,7 @@ export default {
components: {
//8Toolbar,
ActionCell,
ResourceFileIcon,
ResourceIcon,
ResourceFileLink,
DocumentsFilterForm,
DataFilter

@ -67,18 +67,10 @@
field="resourceNode.title"
>
<template #body="slotProps">
<div v-if="slotProps.data && slotProps.data.resourceNode && slotProps.data.resourceNode.resourceFile">
<ResourceFileLink :resource="slotProps.data" />
</div>
<div v-else>
<Button
v-if="slotProps.data"
:label="slotProps.data.resourceNode.title"
class="p-button-text p-button-plain"
icon="mdi mdi-folder"
@click="btnFolderOnClick(slotProps.data)"
/>
</div>
<DocumentEntry
v-if="slotProps.data"
:data="slotProps.data"
/>
</template>
</Column>
@ -109,30 +101,34 @@
>
<template #body="slotProps">
<div class="flex flex-row justify-end gap-2">
<Button
class="p-button-icon-only p-button-plain p-button-outlined p-button-sm"
icon="mdi mdi-information"
<BaseButton
type="black"
icon="information"
size="small"
@click="btnShowInformationOnClick(slotProps.data)"
/>
<Button
<BaseButton
v-if="isAuthenticated && isCurrentTeacher"
:icon="RESOURCE_LINK_PUBLISHED === slotProps.data.resourceLinkListFromEntity[0].visibility ? 'mdi mdi-eye' : (RESOURCE_LINK_DRAFT === slotProps.data.resourceLinkListFromEntity[0].visibility ? 'mdi mdi-eye-off' : '')"
class="p-button-icon-only p-button-plain p-button-outlined p-button-sm"
type="black"
:icon="RESOURCE_LINK_PUBLISHED === slotProps.data.resourceLinkListFromEntity[0].visibility ? 'eye-on' : (RESOURCE_LINK_DRAFT === slotProps.data.resourceLinkListFromEntity[0].visibility ? 'eye-off' : '')"
size="small"
@click="btnChangeVisibilityOnClick(slotProps.data)"
/>
<Button
<BaseButton
v-if="isAuthenticated && isCurrentTeacher"
class="p-button-icon-only p-button-plain p-button-outlined p-button-sm"
icon="mdi mdi-pencil"
type="black"
icon="edit"
size="small"
@click="btnEditOnClick(slotProps.data)"
/>
<Button
<BaseButton
v-if="isAuthenticated && isCurrentTeacher"
class="p-button-icon-only p-button-danger p-button-outlined p-button-sm"
icon="mdi mdi-delete"
type="danger"
icon="delete"
size="small"
@click="confirmDeleteItem(slotProps.data)"
/>
</div>
@ -245,7 +241,6 @@
<script setup>
import { useStore } from 'vuex'
import ResourceFileLink from '../../components/documents/ResourceFileLink.vue'
import { RESOURCE_LINK_DRAFT, RESOURCE_LINK_PUBLISHED } from '../../components/resource_links/visibility'
import { isEmpty } from 'lodash'
import { useRoute, useRouter } from 'vue-router'
@ -258,6 +253,8 @@ import { useDatatableList } from '../../composables/datatableList'
import { useRelativeDatetime } from '../../composables/formatDate'
import axios from 'axios'
import { useToast } from 'primevue/usetoast';
import DocumentEntry from "../../components/documents/DocumentEntry.vue";
import BaseButton from "../../components/basecomponents/BaseButton.vue";
const store = useStore()
const route = useRoute()
@ -427,23 +424,6 @@ function goToUploadFile () {
})
}
function btnFolderOnClick (item) {
const folderParams = route.query;
const resourceId = item.resourceNode.id;
if (!resourceId) {
return;
}
filters.value['resourceNode.parent'] = resourceId;
router.push({
name: 'DocumentsList',
params: { node: resourceId },
query: folderParams,
});
}
function btnShowInformationOnClick (item) {
const folderParams = route.query;

@ -84,7 +84,7 @@ import { mapFields } from 'vuex-map-fields';
import ListMixin from '../../mixins/ListMixin';
import ActionCell from '../../components/ActionCell.vue';
import Toolbar from '../../components/Toolbar.vue';
import ResourceFileIcon from '../../components/documents/ResourceFileIcon.vue';
import ResourceIcon from '../../components/documents/ResourceIcon.vue';
import { useRoute } from 'vue-router'
import moment from 'moment'
@ -96,7 +96,7 @@ export default {
components: {
Toolbar,
ActionCell,
ResourceFileIcon,
ResourceIcon,
},
setup() {
//this.moment = moment;

@ -132,7 +132,7 @@ import { mapActions, mapGetters } from 'vuex';
import { mapFields } from 'vuex-map-fields';
import ListMixin from '../../mixins/ListMixin';
import ActionCell from '../../components/ActionCell.vue';
import ResourceFileIcon from '../../components/documents/ResourceFileIcon.vue';
import ResourceIcon from '../../components/documents/ResourceIcon.vue';
import ResourceFileLink from '../../components/documents/ResourceFileLink.vue';
import { useRoute } from 'vue-router'
@ -149,7 +149,7 @@ export default {
components: {
//8Toolbar,
ActionCell,
ResourceFileIcon,
ResourceIcon,
ResourceFileLink,
//DocumentsFilterForm,
DataFilter

@ -65,7 +65,7 @@ import { mapActions, mapGetters } from 'vuex';
import { mapFields } from 'vuex-map-fields';
import ListMixin from '../../mixins/ListMixin';
import ActionCell from '../../components/ActionCell.vue';
import ResourceFileIcon from '../../components/documents/ResourceFileIcon.vue';
import ResourceIcon from '../../components/documents/ResourceIcon.vue';
import ResourceFileLink from '../../components/documents/ResourceFileLink.vue';
import { useRoute } from 'vue-router'
@ -79,7 +79,7 @@ export default {
components: {
//8Toolbar,
ActionCell,
ResourceFileIcon,
ResourceIcon,
ResourceFileLink,
DataFilter
},

@ -252,7 +252,7 @@ import { mapFields } from 'vuex-map-fields';
import ListMixin from '../../mixins/ListMixin';
import ActionCell from '../../components/ActionCell.vue';
import Toolbar from '../../components/Toolbar.vue';
import ResourceFileIcon from '../../components/documents/ResourceFileIcon.vue';
import ResourceIcon from '../../components/documents/ResourceIcon.vue';
import ResourceFileLink from '../../components/documents/ResourceFileLink.vue';
import {useRoute, useRouter} from 'vue-router'
@ -275,7 +275,7 @@ export default {
components: {
Toolbar,
ActionCell,
ResourceFileIcon,
ResourceIcon,
ResourceFileLink,
DocumentsFilterForm,
DataFilter

@ -173,7 +173,6 @@ import { mapFields } from 'vuex-map-fields';
import ListMixin from '../../mixins/ListMixin';
import ActionCell from '../../components/ActionCell.vue';
import Toolbar from '../../components/Toolbar.vue';
import ResourceFileIcon from '../../components/documents/ResourceFileIcon.vue';
import ResourceFileLink from '../../components/documents/ResourceFileLink.vue';
import DataFilter from '../../components/DataFilter';

@ -11,10 +11,10 @@ module.exports = {
colors: {
primary: {
DEFAULT: "#2e75a3",
gradient: "#9CC2DA",
gradient: "#9cc2da",
},
secondary: {
DEFAULT: "#F37E2F",
DEFAULT: "#f37e2f",
gradient: "#e06410",
},
gray: {

Loading…
Cancel
Save