mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2026-04-15 01:41:56 +00:00
Fix UI and backend paths with subpath (#1799)
I'm not sure if this is an ideal fix for this, but it seems to work for me. If you have another idea just let me know. Closes #1798 Closes #1773
This commit is contained in:
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" fill="white"><path d="M1.263 2.744C2.41 3.832 2.845 4.932 4.118 5.08l.036.007c-.588.606-1.09 1.402-1.443 2.423-.38 1.096-.488 2.285-.614 3.659-.19 2.046-.401 4.364-1.556 7.269-2.486 6.258-1.12 11.63.332 17.317.664 2.604 1.348 5.297 1.642 8.107a.857.857 0 00.633.744.86.86 0 00.922-.323c.227-.313.524-.797.86-1.424.84 3.323 1.355 6.13 1.783 8.697a.866.866 0 001.517.41c2.88-3.463 3.763-8.636 2.184-12.674.459-2.433 1.402-4.45 2.398-6.583.536-1.15 1.08-2.318 1.55-3.566.228-.084.569-.314.79-.441l1.707-.981-.256 1.052a.864.864 0 001.678.408l.68-2.858 1.285-2.95a.863.863 0 10-1.581-.687l-1.152 2.669-2.383 1.372a18.97 18.97 0 00.508-2.981c.432-4.86-.718-9.074-3.066-11.266-.163-.157-.208-.281-.247-.26.095-.12.249-.26.358-.374 2.283-1.693 6.047-.147 8.319.75.589.232.876-.337.316-.67-1.95-1.153-5.948-4.196-8.188-6.193-.313-.275-.527-.607-.89-.913C9.825.555 4.072 3.057 1.355 2.569c-.102-.018-.166.103-.092.175m10.98 5.899c-.06 1.242-.603 1.8-1 2.208-.217.224-.426.436-.524.738-.236.714.008 1.51.66 2.143 1.974 1.84 2.925 5.527 2.538 9.86-.291 3.288-1.448 5.763-2.671 8.385-1.031 2.207-2.096 4.489-2.577 7.259a.853.853 0 00.056.48c1.02 2.434 1.135 6.197-.672 9.46a96.586 96.586 0 00-1.97-8.711c1.964-4.488 4.203-11.75 2.919-17.668-.325-1.497-1.304-3.276-2.387-4.207-.208-.18-.402-.237-.495-.167-.084.06-.151.238-.062.444.55 1.266.879 2.599 1.226 4.276 1.125 5.443-.956 12.49-2.835 16.782l-.116.259-.457.982c-.356-2.014-.85-3.95-1.33-5.84-1.38-5.406-2.68-10.515-.401-16.254 1.247-3.137 1.483-5.692 1.672-7.746.116-1.263.216-2.355.526-3.252.905-2.605 3.062-3.178 4.744-2.852 1.632.316 3.24 1.593 3.156 3.42zm-2.868.62a1.177 1.177 0 10.736-2.236 1.178 1.178 0 10-.736 2.237z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22" fill="white"><path d="M1.263 2.744C2.41 3.832 2.845 4.932 4.118 5.08l.036.007c-.588.606-1.09 1.402-1.443 2.423-.38 1.096-.488 2.285-.614 3.659-.19 2.046-.401 4.364-1.556 7.269-2.486 6.258-1.12 11.63.332 17.317.664 2.604 1.348 5.297 1.642 8.107a.857.857 0 00.633.744.86.86 0 00.922-.323c.227-.313.524-.797.86-1.424.84 3.323 1.355 6.13 1.783 8.697a.866.866 0 001.517.41c2.88-3.463 3.763-8.636 2.184-12.674.459-2.433 1.402-4.45 2.398-6.583.536-1.15 1.08-2.318 1.55-3.566.228-.084.569-.314.79-.441l1.707-.981-.256 1.052a.864.864 0 001.678.408l.68-2.858 1.285-2.95a.863.863 0 10-1.581-.687l-1.152 2.669-2.383 1.372a18.97 18.97 0 00.508-2.981c.432-4.86-.718-9.074-3.066-11.266-.163-.157-.208-.281-.247-.26.095-.12.249-.26.358-.374 2.283-1.693 6.047-.147 8.319.75.589.232.876-.337.316-.67-1.95-1.153-5.948-4.196-8.188-6.193-.313-.275-.527-.607-.89-.913C9.825.555 4.072 3.057 1.355 2.569c-.102-.018-.166.103-.092.175m10.98 5.899c-.06 1.242-.603 1.8-1 2.208-.217.224-.426.436-.524.738-.236.714.008 1.51.66 2.143 1.974 1.84 2.925 5.527 2.538 9.86-.291 3.288-1.448 5.763-2.671 8.385-1.031 2.207-2.096 4.489-2.577 7.259a.853.853 0 00.056.48c1.02 2.434 1.135 6.197-.672 9.46a96.586 96.586 0 00-1.97-8.711c1.964-4.488 4.203-11.75 2.919-17.668-.325-1.497-1.304-3.276-2.387-4.207-.208-.18-.402-.237-.495-.167-.084.06-.151.238-.062.444.55 1.266.879 2.599 1.226 4.276 1.125 5.443-.956 12.49-2.835 16.782l-.116.259-.457.982c-.356-2.014-.85-3.95-1.33-5.84-1.38-5.406-2.68-10.515-.401-16.254 1.247-3.137 1.483-5.692 1.672-7.746.116-1.263.216-2.355.526-3.252.905-2.605 3.062-3.178 4.744-2.852 1.632.316 3.24 1.593 3.156 3.42zm-2.868.62a1.177 1.177 0 10.736-2.236 1.178 1.178 0 10-.736 2.237z"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
@@ -7,7 +7,7 @@
|
||||
<div class="flex items-center space-x-2">
|
||||
<!-- Logo -->
|
||||
<router-link :to="{ name: 'home' }" class="flex flex-col -my-2 px-2">
|
||||
<img class="w-8 h-8" src="../../../assets/logo.svg?url" />
|
||||
<WoodpeckerLogo class="w-8 h-8" />
|
||||
<span class="text-xs">{{ version }}</span>
|
||||
</router-link>
|
||||
<!-- Repo Link -->
|
||||
@@ -57,6 +57,7 @@
|
||||
import { defineComponent } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
import WoodpeckerLogo from '~/assets/logo.svg?component';
|
||||
import Button from '~/components/atomic/Button.vue';
|
||||
import IconButton from '~/components/atomic/IconButton.vue';
|
||||
import useAuthentication from '~/compositions/useAuthentication';
|
||||
@@ -68,7 +69,7 @@ import ActivePipelines from './ActivePipelines.vue';
|
||||
export default defineComponent({
|
||||
name: 'Navbar',
|
||||
|
||||
components: { Button, ActivePipelines, IconButton },
|
||||
components: { Button, ActivePipelines, IconButton, WoodpeckerLogo },
|
||||
|
||||
setup() {
|
||||
const config = useConfig();
|
||||
@@ -76,7 +77,7 @@ export default defineComponent({
|
||||
const authentication = useAuthentication();
|
||||
const { darkMode } = useDarkMode();
|
||||
const docsUrl = config.docs || undefined;
|
||||
const apiUrl = `${config.rootURL ?? ''}/swagger/index.html`;
|
||||
const apiUrl = `${config.rootPath ?? ''}/swagger/index.html`;
|
||||
|
||||
function doLogin() {
|
||||
authentication.authenticate(route.fullPath);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import WoodpeckerIcon from '../../../assets/woodpecker.svg?component';
|
||||
import WoodpeckerIcon from '~/assets/woodpecker.svg?component';
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -48,6 +48,7 @@ import InputField from '~/components/form/InputField.vue';
|
||||
import SelectField from '~/components/form/SelectField.vue';
|
||||
import Panel from '~/components/layout/Panel.vue';
|
||||
import useApiClient from '~/compositions/useApiClient';
|
||||
import useConfig from '~/compositions/useConfig';
|
||||
import { usePaginate } from '~/compositions/usePaginate';
|
||||
import { Repo } from '~/lib/api/types';
|
||||
|
||||
@@ -89,7 +90,7 @@ export default defineComponent({
|
||||
|
||||
const baseUrl = `${window.location.protocol}//${window.location.hostname}${
|
||||
window.location.port ? `:${window.location.port}` : ''
|
||||
}`;
|
||||
}${useConfig().rootPath}`;
|
||||
const badgeUrl = computed(
|
||||
() => `/api/badges/${repo.value.id}/status.svg${branch.value !== '' ? `?branch=${branch.value}` : ''}`,
|
||||
);
|
||||
|
||||
@@ -63,7 +63,7 @@ import useApiClient from '~/compositions/useApiClient';
|
||||
import useConfig from '~/compositions/useConfig';
|
||||
|
||||
const { t } = useI18n();
|
||||
const { enableSwagger } = useConfig();
|
||||
const { rootPath, enableSwagger } = useConfig();
|
||||
|
||||
const apiClient = useApiClient();
|
||||
const token = ref<string | undefined>();
|
||||
@@ -72,7 +72,7 @@ onMounted(async () => {
|
||||
token.value = await apiClient.getToken();
|
||||
});
|
||||
|
||||
const address = `${window.location.protocol}//${window.location.host}`; // port is included in location.host
|
||||
const address = `${window.location.protocol}//${window.location.host}${rootPath}`; // port is included in location.host
|
||||
|
||||
const usageWithShell = computed(() => {
|
||||
let usage = `export WOODPECKER_SERVER="${address}"\n`;
|
||||
|
||||
@@ -7,7 +7,7 @@ let apiClient: WoodpeckerClient | undefined;
|
||||
export default (): WoodpeckerClient => {
|
||||
if (!apiClient) {
|
||||
const config = useConfig();
|
||||
const server = config.rootURL ?? '';
|
||||
const server = config.rootPath;
|
||||
const token = null;
|
||||
const csrf = config.csrf || null;
|
||||
|
||||
|
||||
@@ -12,6 +12,6 @@ export default () =>
|
||||
const config = useUserConfig();
|
||||
config.setUserConfig('redirectUrl', url);
|
||||
}
|
||||
window.location.href = '/login';
|
||||
window.location.href = `${useConfig().rootPath}/login`;
|
||||
},
|
||||
} as const);
|
||||
|
||||
@@ -7,7 +7,7 @@ declare global {
|
||||
WOODPECKER_VERSION: string | undefined;
|
||||
WOODPECKER_CSRF: string | undefined;
|
||||
WOODPECKER_FORGE: string | undefined;
|
||||
WOODPECKER_ROOT_URL: string | undefined;
|
||||
WOODPECKER_ROOT_PATH: string | undefined;
|
||||
WOODPECKER_ENABLE_SWAGGER: boolean | undefined;
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,6 @@ export default () => ({
|
||||
version: window.WOODPECKER_VERSION,
|
||||
csrf: window.WOODPECKER_CSRF || null,
|
||||
forge: window.WOODPECKER_FORGE || null,
|
||||
rootURL: window.WOODPECKER_ROOT_URL || null,
|
||||
rootPath: window.WOODPECKER_ROOT_PATH || '',
|
||||
enableSwagger: window.WOODPECKER_ENABLE_SWAGGER || false,
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { computed, ref, watch } from 'vue';
|
||||
|
||||
import useConfig from '~/compositions/useConfig';
|
||||
import { useDarkMode } from '~/compositions/useDarkMode';
|
||||
import { PipelineStatus } from '~/lib/api/types';
|
||||
|
||||
@@ -13,12 +14,16 @@ watch(
|
||||
() => {
|
||||
const faviconPNG = document.getElementById('favicon-png');
|
||||
if (faviconPNG) {
|
||||
(faviconPNG as HTMLLinkElement).href = `/favicons/favicon-${darkMode.value}-${faviconStatus.value}.png`;
|
||||
(faviconPNG as HTMLLinkElement).href = `${useConfig().rootPath}/favicons/favicon-${darkMode.value}-${
|
||||
faviconStatus.value
|
||||
}.png`;
|
||||
}
|
||||
|
||||
const faviconSVG = document.getElementById('favicon-svg');
|
||||
if (faviconSVG) {
|
||||
(faviconSVG as HTMLLinkElement).href = `/favicons/favicon-${darkMode.value}-${faviconStatus.value}.svg`;
|
||||
(faviconSVG as HTMLLinkElement).href = `${useConfig().rootPath}/favicons/favicon-${darkMode.value}-${
|
||||
faviconStatus.value
|
||||
}.svg`;
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
|
||||
@@ -109,7 +109,7 @@ export default class ApiClient {
|
||||
access_token: this.token || undefined,
|
||||
});
|
||||
let _path = this.server ? this.server + path : path;
|
||||
_path = this.token ? `${path}?${query}` : path;
|
||||
_path = this.token ? `${_path}?${query}` : _path;
|
||||
|
||||
const events = new EventSource(_path);
|
||||
events.onmessage = (event) => {
|
||||
|
||||
@@ -2,16 +2,18 @@ import { Component } from 'vue';
|
||||
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import useAuthentication from '~/compositions/useAuthentication';
|
||||
import useConfig from '~/compositions/useConfig';
|
||||
import useUserConfig from '~/compositions/useUserConfig';
|
||||
|
||||
const { rootPath } = useConfig();
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
path: '/',
|
||||
path: `${rootPath}/`,
|
||||
name: 'home',
|
||||
redirect: '/repos',
|
||||
redirect: `${rootPath}/repos`,
|
||||
},
|
||||
{
|
||||
path: '/repos',
|
||||
path: `${rootPath}/repos`,
|
||||
component: (): Component => import('~/views/RouterView.vue'),
|
||||
children: [
|
||||
{
|
||||
@@ -105,7 +107,7 @@ const routes: RouteRecordRaw[] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/orgs/:orgId',
|
||||
path: `${rootPath}/orgs/:orgId`,
|
||||
component: (): Component => import('~/views/org/OrgWrapper.vue'),
|
||||
props: true,
|
||||
children: [
|
||||
@@ -125,12 +127,12 @@ const routes: RouteRecordRaw[] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/org/:orgName/:pathMatch(.*)*',
|
||||
path: `${rootPath}/org/:orgName/:pathMatch(.*)*`,
|
||||
component: (): Component => import('~/views/org/OrgDeprecatedRedirect.vue'),
|
||||
props: true,
|
||||
},
|
||||
{
|
||||
path: '/admin',
|
||||
path: `${rootPath}/admin`,
|
||||
name: 'admin-settings',
|
||||
component: (): Component => import('~/views/admin/AdminSettings.vue'),
|
||||
props: true,
|
||||
@@ -138,21 +140,21 @@ const routes: RouteRecordRaw[] = [
|
||||
},
|
||||
|
||||
{
|
||||
path: '/user',
|
||||
path: `${rootPath}/user`,
|
||||
name: 'user',
|
||||
component: (): Component => import('~/views/User.vue'),
|
||||
meta: { authentication: 'required' },
|
||||
props: true,
|
||||
},
|
||||
{
|
||||
path: '/login/error',
|
||||
path: `${rootPath}/login/error`,
|
||||
name: 'login-error',
|
||||
component: (): Component => import('~/views/Login.vue'),
|
||||
meta: { blank: true },
|
||||
props: true,
|
||||
},
|
||||
{
|
||||
path: '/do-login',
|
||||
path: `${rootPath}/do-login`,
|
||||
name: 'login',
|
||||
component: (): Component => import('~/views/Login.vue'),
|
||||
meta: { blank: true },
|
||||
@@ -161,18 +163,18 @@ const routes: RouteRecordRaw[] = [
|
||||
|
||||
// TODO: deprecated routes => remove after some time
|
||||
{
|
||||
path: '/:ownerOrOrgId',
|
||||
path: `${rootPath}/:ownerOrOrgId`,
|
||||
redirect: (route) => ({ name: 'org', params: route.params }),
|
||||
},
|
||||
{
|
||||
path: '/:repoOwner/:repoName/:pathMatch(.*)*',
|
||||
path: `${rootPath}/:repoOwner/:repoName/:pathMatch(.*)*`,
|
||||
component: () => import('~/views/repo/RepoDeprecatedRedirect.vue'),
|
||||
props: true,
|
||||
},
|
||||
|
||||
// not found handler
|
||||
{
|
||||
path: '/:pathMatch(.*)*',
|
||||
path: `${rootPath}/:pathMatch(.*)*`,
|
||||
name: 'not-found',
|
||||
component: (): Component => import('~/views/NotFound.vue'),
|
||||
},
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
class="flex flex-col w-full overflow-hidden md:m-8 md:rounded-md md:shadow md:border md:border-wp-background-400 md:bg-wp-background-100 md:dark:bg-wp-background-200 md:flex-row md:w-3xl md:h-sm justify-center"
|
||||
>
|
||||
<div class="flex md:bg-wp-primary-200 md:dark:bg-wp-primary-300 md:w-3/5 justify-center items-center">
|
||||
<img class="w-48 h-48" src="../assets/logo.svg?url" />
|
||||
<WoodpeckerLogo class="w-48 h-48" />
|
||||
</div>
|
||||
<div class="flex flex-col my-8 md:w-2/5 p-4 items-center justify-center">
|
||||
<h1 class="text-xl text-wp-text-100">{{ $t('welcome') }}</h1>
|
||||
@@ -27,6 +27,7 @@ import { defineComponent, onMounted, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
|
||||
import WoodpeckerLogo from '~/assets/logo.svg?component';
|
||||
import Button from '~/components/atomic/Button.vue';
|
||||
import useAuthentication from '~/compositions/useAuthentication';
|
||||
|
||||
@@ -35,6 +36,7 @@ export default defineComponent({
|
||||
|
||||
components: {
|
||||
Button,
|
||||
WoodpeckerLogo,
|
||||
},
|
||||
|
||||
setup() {
|
||||
|
||||
@@ -16,6 +16,7 @@ import Scaffold from '~/components/layout/scaffold/Scaffold.vue';
|
||||
import Tab from '~/components/layout/scaffold/Tab.vue';
|
||||
import UserAPITab from '~/components/user/UserAPITab.vue';
|
||||
import UserGeneralTab from '~/components/user/UserGeneralTab.vue';
|
||||
import useConfig from '~/compositions/useConfig';
|
||||
|
||||
const address = `${window.location.protocol}//${window.location.host}`; // port is included in location.host
|
||||
const address = `${window.location.protocol}//${window.location.host}${useConfig().rootPath}`; // port is included in location.host
|
||||
</script>
|
||||
|
||||
@@ -123,7 +123,7 @@ watch([repositoryId], () => {
|
||||
loadRepo();
|
||||
});
|
||||
|
||||
const badgeUrl = computed(() => repo.value && `/api/badges/${repo.value.id}/status.svg`);
|
||||
const badgeUrl = computed(() => repo.value && `${config.rootPath}/api/badges/${repo.value.id}/status.svg`);
|
||||
|
||||
const activeTab = computed({
|
||||
get() {
|
||||
|
||||
Reference in New Issue
Block a user