Skip to content
Merged
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
24 changes: 20 additions & 4 deletions src/backend/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,26 @@ export const getCurrentPolicies = async () => {
return data.items
}

export const getPolicyByDate = async ({ policyType, activeFrom }) => {
const { data } = await axios.get(`/v1/policies/${policyType}/by_active_from/${activeFrom}`)
return data
}

export const getAllPoliciesByType = async ({ policyType }) => {
const { data } = await axios.get(`/v1/policies/${policyType}`)
return data.items
}

export const getCurrentPolicyByType = async ({ policyType }) => {
const { data } = await axios.get(`/v1/policies/${policyType}/current`)
return data
}

export const getUpcomingPolicyByType = async ({ policyType }) => {
const { data } = await axios.get(`/v1/policies/${policyType}/upcoming`)
return data
}

/* Wiki endpoints */
export const countWikis = async () => (await axios.get('/wiki/count')).data.data // TODO This doesn't seem to exist and not used?
export const myWikis = async () => (await axios.post('/wiki/mine')).data
Expand Down Expand Up @@ -102,10 +122,6 @@ export const wikiDiscovery = async ({ sort, direction, active, currentPage, resu
})).data
}

export const policyByDate = async ({ policyType, activeFrom }) => {
return (await axios.get(`/v1/policies/${policyType}/by_active_from/${activeFrom}`)).data
}

export const importEntities = async ({
wikiId,
entityIds = [
Expand Down
2 changes: 1 addition & 1 deletion src/components/Layout/Foot.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<ul class="footer-list">
<li><router-link to="/privacy-policy">Privacy Policy</router-link></li>
<li><router-link to="/terms-of-use">Terms of Use</router-link></li>
<li><router-link to="/hosting-policy/pilot">Hosting Policy</router-link></li>
<li><router-link to="/hosting-policy">Hosting Policy</router-link></li>
<li><router-link to="/dsa-info">Digital Services Act Information</router-link></li>
<li><a target="_blank" rel="noopener noreferrer" href="https://www.wikimedia.de/impressum/">Imprint</a></li>
<li><router-link to="/complaint">Report illegal content</router-link></li>
Expand Down
141 changes: 135 additions & 6 deletions src/components/Pages/Components/PolicyNavigationPanel.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<template>
<v-expansion-panels v-bind:value="$vuetify.breakpoint.mdAndUp ? 0 : null" v-if="links">
<v-expansion-panels v-bind:value="$vuetify.breakpoint.mdAndUp ? 0 : null" v-if="links && links.length">
<v-expansion-panel>
<v-expansion-panel-header class="grey lighten-3">{{ title }}</v-expansion-panel-header>

<v-expansion-panel-content>
<v-list class="wrap">
<v-list-item v-for="(link, index) in links" :key="link.routePath">
<v-list-item-content>
<v-list-item-title v-if="index == currentLink">
<v-list-item-title v-if="index == currentlyRenderedLink">
{{ link.title }}
</v-list-item-title>

Expand All @@ -25,12 +25,141 @@
</template>

<script>

export default {
name: 'NavigationPanel',
name: 'PolicyNavigationPanel',
components: {
},
props: {
title: String,
currentLink: Number,
links: Array,
basePath: {
type: String,
},
policyType: {
type: String,
},
title: {
type: String,
default: 'All Versions',
},
},
data: () => ({
policies: [],
currentPolicyId: null,
upcomingPolicyId: null,
error: undefined,
}),
computed: {
links: function () {
const policyById = new Map(this.policies.map(policy => [policy.metadata.policy_id, policy]))
const currentPolicy = policyById.get(this.currentPolicyId)
const upcomingPolicy = policyById.get(this.upcomingPolicyId)

const otherPolicies = this.policies.filter(policy => {
const policyId = policy.metadata.policy_id
const currentPolicyId = this.currentPolicyId
const upcomingPolicyId = this.upcomingPolicyId

return policyId !== currentPolicyId && policyId !== upcomingPolicyId
}).sort((left, right) => {
const leftActiveFrom = left.metadata.active_from || ''
const rightActiveFrom = right.metadata.active_from || ''

if (leftActiveFrom === rightActiveFrom) {
return right.metadata.policy_id - left.metadata.policy_id
}

return rightActiveFrom.localeCompare(leftActiveFrom)
})

const orderedPolicies = [upcomingPolicy, currentPolicy, ...otherPolicies].filter(Boolean)

return orderedPolicies.map(policy => {
const activeFrom = policy.metadata.active_from
const isCurrentPolicy = currentPolicy && policy.metadata.policy_id === currentPolicy.metadata.policy_id
const isUpcomingPolicy = upcomingPolicy && policy.metadata.policy_id === upcomingPolicy.metadata.policy_id

return {
routePath: this.routePathForPolicy({ activeFrom, isCurrentPolicy, isUpcomingPolicy }),
title: this.titleForPolicy({ activeFrom, isCurrentPolicy, isUpcomingPolicy }),
}
})
},
currentlyRenderedLink: function () {
const isRenderedPath = (element) => element.routePath === this.$route.path
const positionInList = this.links.findIndex(isRenderedPath)

if (positionInList === -1) {
const renderedVersionIndex = this.links.findIndex(element => element.routePath === this.basePath)
return renderedVersionIndex === -1 ? 0 : renderedVersionIndex
}

return positionInList
},
},
methods: {
async loadPolicies () {
this.error = undefined

try {
const policies = await this.$api.getAllPoliciesByType({ policyType: this.policyType })

this.policies = policies

// We look up the Current and Upcoming policy of this type to avoid needing to have the complex
// date calculations in the frontend and instead do them in the platform api.
// This is quite inefficient but it keeps the frontend less complex to reason about.
// We need to consider that there may be neither an upcoming or current policy and gracefully handle that,
try {
const upcomingPolicy = await this.$api.getUpcomingPolicyByType({ policyType: this.policyType })
this.upcomingPolicyId = upcomingPolicy.metadata.policy_id
} catch (error) {
if (!(error && error.response && error.response.status === 404)) {
console.error(error)
}
this.upcomingPolicyId = null
}

try {
const currentPolicy = await this.$api.getCurrentPolicyByType({ policyType: this.policyType })
this.currentPolicyId = currentPolicy.metadata.policy_id
} catch (error) {
if (!(error && error.response && error.response.status === 404)) {
console.error(error)
}
this.currentPolicyId = null
}
} catch (error) {
this.error = error
console.error(error)
}
},
routePathForPolicy ({ activeFrom, isCurrentPolicy, isUpcomingPolicy }) {
if (isCurrentPolicy) {
return this.basePath
}

if (isUpcomingPolicy) {
return `${this.basePath}/upcoming`
}

return `${this.basePath}/${activeFrom}`
},
titleForPolicy ({ activeFrom, isCurrentPolicy, isUpcomingPolicy }) {
if (isCurrentPolicy) {
return 'Current version'
}
if (isUpcomingPolicy) {
return 'Upcoming version'
}

return activeFrom
},
},
mounted () {
this.loadPolicies()
},
}

</script>

<style scoped></style>
48 changes: 43 additions & 5 deletions src/components/Pages/HostingPolicy/HostingPolicyRenderer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@
<v-container class="fill-height" fluid v-if="!error">
<v-row justify="center">
<v-col cols="11" md="4" order-md="last">
<PolicyNavigationPanel basePath="/hosting-policy" policyType="hosting-policy" />
</v-col>

<v-col cols="11" md="8">
<v-alert type="info" v-if="isUpcomingRoute">
This is an upcoming version. You can find the
<router-link class="white--text" to="/hosting-policy">current version here</router-link>.
</v-alert>

<component :is="policy" v-if="policy" />
</v-col>
</v-row>
Expand All @@ -18,37 +24,66 @@

<script>

import PolicyNavigationPanel from '../Components/PolicyNavigationPanel.vue'

export const versions = {
'hosting-policy/version-1.vue': () => ({ component: import('./hosting-policy/version-1.vue') }),
}

export default {
name: 'HostingPolicyRenderer',
components: {},
components: {
PolicyNavigationPanel,
},
computed: {
policyActiveFrom: function () {
return this.$route.params.activeFrom
},
isUpcomingRoute: function () {
return this.$route.path === '/hosting-policy/upcoming'
},
isCurrentRoute: function () {
return this.policyActiveFrom === undefined
},
},
data () {
return {
policy: undefined,
policyMetadata: undefined,
error: undefined,
policyType: 'hosting-policy',
}
},
methods: {
async loadPolicy () {
this.policy = undefined
this.policyMetadata = undefined
this.error = undefined

try {
const policyType = 'hosting-policy' // TODO read this from component property
const policyType = this.policyType // TODO for a generalized component, read this from component property
const activeFrom = this.policyActiveFrom
let response

const response = await this.$api.policyByDate({ policyType, activeFrom })
if (this.isUpcomingRoute) {
response = await this.$api.getUpcomingPolicyByType({ policyType })
} else if (this.isCurrentRoute) {
response = await this.$api.getCurrentPolicyByType({ policyType })
if (response === undefined) {
// Special case to redirect users to the pilot policy if there is no current policy
// Remove afer T408316
this.$router.replace({ path: '/hosting-policy/pilot' })
}
} else {
response = await this.$api.getPolicyByDate({ policyType, activeFrom })
}

const metadata = await response.metadata
const metadata = response.metadata
const policy = versions[metadata.content_vue_file]

if (policy !== undefined) {
this.policy = policy
this.policyMetadata = metadata
} else {
this.error = 'missing policy'
}
Expand All @@ -62,7 +97,10 @@ export default {
this.loadPolicy()
},
watch: {
policyId: function () {
policyActiveFrom: function () {
this.loadPolicy()
},
isUpcomingRoute: function () {
this.loadPolicy()
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@
</template>

<script>
// Legacy file. Remove after T408316
export default {
name: 'HostingPolicy',
}
Expand Down
37 changes: 0 additions & 37 deletions src/components/Pages/TermsOfUse/TermsOfUseNavigationPanel.vue

This file was deleted.

Loading
Loading