{"version":3,"file":"RightsWrapper-lnk_ospr.mjs","names":[],"sources":["../src/components/composable/useRightsIndicator.ts","../src/components/display/RightsWrapper.vue","../src/components/display/RightsWrapper.vue"],"sourcesContent":["import { Mix } from '../../stores/class/radio/mix';\nimport { PlaylistMedia } from '../../stores/class/radio/playlistMedia';\nimport { Podcast } from '../../stores/class/general/podcast';\nimport { Cartouchier } from '../../stores/class/cartouchier/cartouchier';\nimport { Media } from \"../../stores/class/general/media\";\nimport { computed } from 'vue';\nimport { useI18n } from 'vue-i18n';\nimport { ActionRight, useRights } from '../composable/useRights';\nimport { state } from '../../stores/ParamSdkStore';\nimport { useAuthStore } from '../../stores/AuthStore';\nimport { storeToRefs } from 'pinia';\nimport { Emission } from '@/stores/class/general/emission';\n\ntype Action = 'create'|'edit'|'delete'|'any';\n\nexport interface PropsBase {\n    /** Type of action to check */\n    action: Action;\n}\n\ntype NeverEntities = {\n    podcast?: never;\n    emission?: never;\n    cartouchier?: never;\n    mix?: never;\n    playlistMedia?: never;\n    media?: never;\n    promoVideoFor?: never;\n};\n\nexport interface PropsPodcast extends PropsBase, Omit<NeverEntities, 'podcast'> {\n    podcast: Podcast|boolean;\n}\nexport interface PropsEmission extends PropsBase, Omit<NeverEntities, 'emission'> {\n    emission: Emission|boolean;\n}\nexport interface PropsCartouchier extends PropsBase, Omit<NeverEntities, 'cartouchier'> {\n    cartouchier: Cartouchier|boolean;\n}\nexport interface PropsMix extends PropsBase, Omit<NeverEntities, 'mix'> {\n    mix: Mix|boolean;\n}\nexport interface PropsPlaylistMedia extends PropsBase, Omit<NeverEntities, 'playlistMedia'> {\n    playlistMedia: PlaylistMedia|boolean;\n}\nexport interface PropsMedia extends PropsBase, Omit<NeverEntities, 'media'> {\n    media: Media|boolean;\n}\nexport interface PropsPromoVideo extends PropsBase, Omit<NeverEntities, 'promoVideoFor'> {\n    promoVideoFor: Podcast;\n}\n\nexport type RightsProps = PropsPodcast|PropsEmission|PropsCartouchier|PropsMix|PropsPlaylistMedia|PropsMedia;\n\nexport const useRightsIndicator = (props: PropsPodcast|PropsEmission|PropsCartouchier|PropsMix|PropsPlaylistMedia|PropsMedia) => {\n    const rights = useRights();\n    const { t, te } = useI18n();\n    const { isAuthenticated } = storeToRefs(useAuthStore());\n\n    type Rights = ReturnType<typeof useRights>;\n    type ActionSegment = 'Create'|'Edit'|'Delete';\n    type EntitySegment = 'Podcast'|'Emission'|'Cartouchier'|'Mix'|'PlaylistMedia'|'Media'|'PromoVideo';\n    type RightMethodKey = `get${ActionSegment}${EntitySegment}Right` & keyof Rights;\n    type RightEntity = Podcast|Emission|Cartouchier|Mix|PlaylistMedia|Media|boolean|undefined;\n\n    const actionSegmentMap: Record<Exclude<Action, 'any'>, ActionSegment> = {\n        create: 'Create',\n        edit: 'Edit',\n        delete: 'Delete',\n    };\n\n    /**\n     * Whether to display the indicator\n     * It is not shown on podcastmaker, or for unidentified users\n     */\n    const displayIndicator = computed((): boolean => {\n        return !state.generalParameters.podcastmaker && isAuthenticated.value;\n    });\n\n    /**\n     * The entity on which rights are checked\n     */\n    const entity = computed((): [EntitySegment, RightEntity]|null => {\n        let arg: RightEntity;\n        let entitySegment: EntitySegment|undefined;\n\n        if ('podcast' in props && props.podcast) {\n            entitySegment = 'Podcast';\n            arg = props.podcast;\n        } else if ('emission' in props && props.emission) {\n            entitySegment = 'Emission';\n            arg = props.emission;\n        } else if ('cartouchier' in props && props.cartouchier) {\n            entitySegment = 'Cartouchier';\n            arg = props.cartouchier;\n        } else if ('mix' in props && props.mix) {\n            entitySegment = 'Mix';\n            arg = props.mix;\n        } else if ('playlistMedia' in props && props.playlistMedia) {\n            entitySegment = 'PlaylistMedia';\n            arg = props.playlistMedia;\n        } else if ('media' in props && props.media) {\n            entitySegment = 'Media';\n            arg = props.media;\n        } else if ('promoVideoFor' in props && props.promoVideoFor) {\n            entitySegment = 'PromoVideo';\n            arg = props.promoVideoFor;\n        } else {\n            return null;\n        }\n\n        return [entitySegment, arg];\n    });\n\n    /**\n     * The current rights for the given entity\n     */\n    const actionRight = computed((): ActionRight => {\n        const data = entity.value;\n        if (!data) {\n            return ActionRight.DeniedNoRight;\n        }\n\n        const [entitySegment, arg] = data;\n\n        if (props.action === 'any') {\n            const checks: ActionSegment[] = typeof arg === 'object' && arg !== null\n                ? ['Create', 'Edit', 'Delete']\n                : ['Create'];\n\n            let best = ActionRight.DeniedNoRight;\n            for (const a of checks) {\n                const key = `get${a}${entitySegment}Right` as RightMethodKey;\n                const r = callRightMethod(key, arg);\n                if (r === ActionRight.Allowed) {\n                    return ActionRight.Allowed;\n                }\n                if (r === ActionRight.DeniedNotOwner) {\n                    best = ActionRight.DeniedNotOwner;\n                }\n            }\n            return best;\n        }\n\n        if ((props.action === 'edit' || props.action === 'delete') && typeof arg !== 'object') {\n            return ActionRight.DeniedNoRight;\n        }\n\n        const methodName = `get${actionSegmentMap[props.action]}${entitySegment}Right` as RightMethodKey;\n        return callRightMethod(methodName, arg);\n    });\n\n    /** Helper for calling the method on useRights */\n    function callRightMethod(key: RightMethodKey, arg: unknown): ActionRight {\n        return (rights[key] as (arg?: unknown) => ActionRight)(arg);\n    }\n\n    const hasAccess = computed((): boolean => {\n        return actionRight.value === ActionRight.Allowed;\n    });\n\n    const message = computed((): string => {\n        const entitySegment = entity.value?.[0];\n        let key: string;\n        let genericKey: string;\n    \n        switch (actionRight.value) {\n        case ActionRight.Allowed:\n            return '';\n\n        case ActionRight.DeniedNotOwner:\n            key = `RightsIndicator - ${entitySegment} - Not owner`;\n            genericKey = 'Generic - Action disabled - Not owner';\n            break;\n\n        case ActionRight.DeniedInsufficientScope:\n            key = `RightsIndicator - ${entitySegment} - Insufficient scope`;\n            genericKey = 'RightsIndicator - Generic - Insufficient scope';\n            break;\n\n        case ActionRight.DeniedNoRight:\n            key = `RightsIndicator - ${entitySegment} - Insufficient rights`;\n            genericKey = 'RightsIndicator - Generic - Insufficient rights';\n            break;\n\n        default:\n            return 'Cannot process rights';\n        }\n\n        if (te(key)) {\n            return t(key);\n        } else {\n            return t(genericKey);\n        }\n    });\n\n    return {\n        displayIndicator,\n        hasAccess,\n        message\n    }\n};\n","<template>\n    <div\n        v-if=\"displayIndicator\"\n    >\n        <slot :id=\"elementId\" :has-access=\"hasAccess\" />\n        <span v-if=\"!hasAccess\" class=\"rights-visually-hidden\">{{ message }}</span>\n        <ClassicPopover\n            v-if=\"!hasAccess\"\n            :target=\"elementId\"\n            only-mouse\n        >\n            {{ message }}\n        </ClassicPopover>\n    </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, getCurrentInstance } from 'vue';\nimport { RightsProps, useRightsIndicator } from '../composable/useRightsIndicator';\nimport ClassicPopover from '../misc/ClassicPopover.vue';\n\nconst props = defineProps<RightsProps>();\n\nconst { displayIndicator, hasAccess, message } = useRightsIndicator(props);\n\nconst uid = getCurrentInstance()?.uid;\n/** ID of the icon for reference by the popover */\nconst elementId = computed((): string => 'rights-wrapper-' + uid);\n</script>\n\n<style scoped lang=\"scss\">\n/** Helper class to keep the data accessible for screen readers */\n.rights-visually-hidden {\n    position: absolute;\n    width: 1px;\n    height: 1px;\n    padding: 0;\n    margin: -1px;\n    overflow: hidden;\n    clip: rect(0, 0, 0, 0);\n    white-space: nowrap;\n    border: 0;\n}\n</style>\n","<template>\n    <div\n        v-if=\"displayIndicator\"\n    >\n        <slot :id=\"elementId\" :has-access=\"hasAccess\" />\n        <span v-if=\"!hasAccess\" class=\"rights-visually-hidden\">{{ message }}</span>\n        <ClassicPopover\n            v-if=\"!hasAccess\"\n            :target=\"elementId\"\n            only-mouse\n        >\n            {{ message }}\n        </ClassicPopover>\n    </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, getCurrentInstance } from 'vue';\nimport { RightsProps, useRightsIndicator } from '../composable/useRightsIndicator';\nimport ClassicPopover from '../misc/ClassicPopover.vue';\n\nconst props = defineProps<RightsProps>();\n\nconst { displayIndicator, hasAccess, message } = useRightsIndicator(props);\n\nconst uid = getCurrentInstance()?.uid;\n/** ID of the icon for reference by the popover */\nconst elementId = computed((): string => 'rights-wrapper-' + uid);\n</script>\n\n<style scoped lang=\"scss\">\n/** Helper class to keep the data accessible for screen readers */\n.rights-visually-hidden {\n    position: absolute;\n    width: 1px;\n    height: 1px;\n    padding: 0;\n    margin: -1px;\n    overflow: hidden;\n    clip: rect(0, 0, 0, 0);\n    white-space: nowrap;\n    border: 0;\n}\n</style>\n"],"mappings":"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"}