Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions src/components/pages/Plugin.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<template>
<div class="plugin-page">
<h1>Plugin</h1>
{{ plugin?.name }}

<iframe
class="plugin-iframe"
:src="pluginUrl"
frameborder="0"
allowfullscreen
referrerpolicy="same-origin"
></iframe>
</div>
</template>

<script setup>
import { useRoute } from 'vue-router'
import { useStore } from 'vuex'
import { computed } from 'vue'
import { useHead } from '@unhead/vue'

const route = useRoute()
const store = useStore()

const plugins = computed(() => store.getters.studioPlugins || [])
const productionId = computed(() => route.params.production_id || '')
const episodeId = computed(() =>
store.getters.isTVShow && productionId.value
? store.getters.currentEpisode?.id
: ''
)
const isDarkTheme = computed(() => store.getters.isDarkTheme)

const pluginUrl = computed(() => {
const baseUrl = `/api/plugins/${route.params.plugin_id}/frontend/`
const params = new URLSearchParams()

if (productionId.value) {
params.append('production_id', productionId.value)
}
if (episodeId.value) {
params.append('episode_id', episodeId.value)
}
if (isDarkTheme.value) {
params.append('dark_theme', isDarkTheme.value)
}

return `${baseUrl}?${params.toString()}`
})

const plugin = computed(() => {
return plugins.value.find(
plugin => plugin.plugin_id === route.params.plugin_id
)
})

useHead({
title: computed(() => {
if (plugin.value) {
return `Kitsu | ${plugin.value.name}`
}
return 'Kitsu | Plugin'
})
})
</script>

<style lang="scss" scoped>
.plugin-page {
padding-top: 20px;
}

.plugin-iframe {
background-color: $white;
width: 100%;
height: calc(100vh - 68px);
border: none;
padding: 0;
margin: 0;
}
</style>
20 changes: 18 additions & 2 deletions src/components/sides/Sidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,19 @@
</router-link>
</p>
</div>
<div v-for="plugin in studioPlugins" :key="plugin.id">
<p @click="toggleSidebar()">
<router-link
:to="{
name: 'plugin',
params: { plugin_id: plugin.plugin_id }
}"
>
<icon :name="plugin.icon" />
{{ plugin.name }}
</router-link>
</p>
</div>

<div v-if="isCurrentUserAdmin">
<h2>{{ $t('main.admin') }}</h2>
Expand Down Expand Up @@ -236,6 +249,7 @@ import {
GlobeIcon,
Rows4Icon
} from 'lucide-vue-next'
import Icon from '@/components/widgets/Icon.vue'

import KitsuIcon from '@/components/widgets/KitsuIcon.vue'

Expand All @@ -248,7 +262,8 @@ export default {
EggIcon,
GlobeIcon,
KitsuIcon,
Rows4Icon
Rows4Icon,
Icon
},

data() {
Expand All @@ -272,7 +287,8 @@ export default {
'isCurrentUserVendor',
'isSidebarHidden',
'mainConfig',
'organisation'
'organisation',
'studioPlugins'
]),

isLongLocale() {
Expand Down
29 changes: 24 additions & 5 deletions src/components/tops/Topbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -302,8 +302,9 @@ export default {
'notifications',
'openProductions',
'organisation',
'productionMap',
'productionEditTaskTypes',
'productionMap',
'projectPlugins',
'user'
]),

Expand Down Expand Up @@ -369,10 +370,12 @@ export default {
},

isEpisodeContext() {
const isPlugin = this.$route.params.plugin_id !== undefined
return (
this.isTVShow &&
this.hasEpisodeId &&
!['episodes', 'episode-stats'].includes(this.currentSectionOption) &&
(!['episodes', 'episode-stats'].includes(this.currentSectionOption) ||
isPlugin) &&
// Do not display combobox if there is no episode
this.episodes.length > 0
)
Expand Down Expand Up @@ -484,6 +487,16 @@ export default {
}
options.push({ label: this.$t('people.team'), value: 'team' })

this.projectPlugins.forEach(plugin => {
options.push({
label: plugin.name,
value: plugin.plugin_id,
icon: plugin.icon,
plugin_id: plugin.plugin_id,
type: 'plugin'
})
})

if (this.isCurrentUserManager) {
options = options.concat([
{ label: 'separator', value: 'separator' },
Expand Down Expand Up @@ -551,6 +564,9 @@ export default {
]),

getCurrentSectionFromRoute() {
if (this.$route.name.includes('production-plugin')) {
return this.$route.params.plugin_id
}
if (this.$route.name === 'person') {
return 'person'
}
Expand Down Expand Up @@ -703,11 +719,13 @@ export default {

updateCombosFromRoute() {
const productionId = this.$route.params.production_id
const pluginId = this.$route.params.plugin_id
const section = this.getCurrentSectionFromRoute()
let episodeId = this.$route.params.episode_id
this.silent = true
this.currentProductionId = productionId
this.currentProjectSection = section
this.currentPluginId = pluginId
const isAssetSection = this.assetSections.includes(section)
const isEditSection = this.editSections.includes(section)
const isBreakdownSection = this.breakdownSections.includes(section)
Expand All @@ -719,13 +737,13 @@ export default {
) {
episodeId = this.episodes[0].id
this.currentEpisodeId = episodeId
this.pushContextRoute(section)
this.pushContextRoute(section, pluginId)
} else {
this.currentEpisodeId = episodeId
}
},

pushContextRoute(section) {
pushContextRoute(section, pluginId = null) {
const isAssetSection = this.assetSections.includes(section)
const production = this.productionMap.get(this.currentProductionId)
const isTVShow = production?.production_type === 'tvshow'
Expand All @@ -742,7 +760,8 @@ export default {
let route = {
name: section,
params: {
production_id: this.currentProductionId
production_id: this.currentProductionId,
plugin_id: pluginId
}
}
route = this.episodifyRoute(route, section, episodeId, isTVShow)
Expand Down
8 changes: 7 additions & 1 deletion src/components/tops/TopbarEpisodeList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,14 @@ export default {
getEpisodePath() {
const currentProduction = this.currentProduction
const section = this.section
const pluginId = this.$route.params.plugin_id
return episodeId => {
const path = getProductionPath(currentProduction, section, episodeId)
const path = getProductionPath(
currentProduction,
section,
episodeId,
pluginId
)
return path
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/components/tops/TopbarProductionList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,12 @@ export default {
},

getProductionPath(production) {
const pluginId = this.$route.params.plugin_id
return getProductionPath(
production,
this.section,
this.episodeId || 'all'
this.episodeId || 'all',
pluginId
)
}
}
Expand Down
32 changes: 26 additions & 6 deletions src/components/tops/TopbarSectionList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,15 @@
class="selected-section-line flexrow-item flexrow"
v-if="currentSection"
>
<icon
class="section-icon"
:name="currentSection.icon"
v-if="currentSection.type === 'plugin'"
/>
<kitsu-icon
class="section-icon"
:name="currentSection.value"
v-if="currentSection.value !== 'budget'"
v-else-if="currentSection.value !== 'budget'"
/>
<hand-coins-icon
class="section-icon"
Expand All @@ -35,7 +40,19 @@
<router-link
class="flexrow"
:to="getSectionPath(section)"
v-if="section.value !== 'separator'"
v-if="section.type === 'plugin'"
>
<icon
class="section-icon"
:name="section.icon"
v-if="section.type === 'plugin'"
/>
<span class="flexrow-item">{{ section.label }}</span>
</router-link>
<router-link
class="flexrow"
:to="getSectionPath(section)"
v-else-if="section.value !== 'separator'"
>
<kitsu-icon
class="section-icon"
Expand Down Expand Up @@ -67,15 +84,17 @@ import { getProductionPath } from '@/lib/path'

import ComboboxMask from '@/components/widgets/ComboboxMask.vue'
import KitsuIcon from '@/components/widgets/KitsuIcon.vue'
import Icon from '@/components/widgets/Icon.vue'

export default {
name: 'topbar-section-list',

components: {
ChevronDownIcon,
ComboboxMask,
KitsuIcon,
HandCoinsIcon
HandCoinsIcon,
Icon,
KitsuIcon
},

emits: ['input'],
Expand Down Expand Up @@ -107,7 +126,7 @@ export default {
},

computed: {
...mapGetters(['currentProduction']),
...mapGetters(['currentProduction', 'projectPlugins']),

currentSection() {
return this.sectionList.find(
Expand Down Expand Up @@ -135,7 +154,8 @@ export default {
const result = getProductionPath(
this.currentProduction,
section.value,
this.episodeId
this.episodeId,
section.plugin_id
)
return result
}
Expand Down
31 changes: 31 additions & 0 deletions src/components/widgets/Icon.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<template>
<component
:is="icon"
:size="size"
:color="color"
:stroke-width="strokeWidth"
:default-class="defaultClass"
/>
</template>

<script setup>
import { computed } from 'vue'
import stringHelpers from '@/lib/string'
import * as icons from 'lucide-vue-next'

const props = defineProps({
name: {
type: String,
required: true
},
size: Number,
color: String,
strokeWidth: Number,
defaultClass: String
})

const iconName = stringHelpers.capitalize(
stringHelpers.snakeToCamel(props.name)
)
const icon = computed(() => icons[iconName])
</script>
Loading
Loading