* New Version: 3.0.0
This commit is contained in:
Andras Bacsai
2022-07-06 11:02:36 +02:00
committed by GitHub
parent 9137e8bc32
commit 87ba4560ad
491 changed files with 16824 additions and 20459 deletions

View File

@@ -0,0 +1,217 @@
<script lang="ts">
export let source: any;
export let settings: any;
import { page } from '$app/stores';
import { post } from '$lib/api';
import Explainer from '$lib/components/Explainer.svelte';
import { toast } from '@zerodevx/svelte-toast';
import { t } from '$lib/translations';
import { dashify, errorNotification, getDomain } from '$lib/common';
import { appSession } from '$lib/store';
import { dev } from '$app/env';
const { id } = $page.params;
let loading = false;
async function handleSubmit() {
loading = true;
try {
await post(`/sources/${id}`, {
name: source.name,
htmlUrl: source.htmlUrl.replace(/\/$/, ''),
apiUrl: source.apiUrl.replace(/\/$/, '')
});
toast.push('Settings saved.');
} catch (error) {
return errorNotification(error);
} finally {
loading = false;
}
}
async function installRepositories(source: any) {
const { htmlUrl } = source;
const left = screen.width / 2 - 1020 / 2;
const top = screen.height / 2 - 1000 / 2;
const newWindow = open(
`${htmlUrl}/apps/${source.githubApp.name}/installations/new`,
'GitHub',
'resizable=1, scrollbars=1, fullscreen=0, height=1000, width=1020,top=' +
top +
', left=' +
left +
', toolbar=0, menubar=0, status=0'
);
const timer = setInterval(() => {
if (newWindow?.closed) {
clearInterval(timer);
window.location.reload();
}
}, 100);
}
async function newGithubApp() {
loading = true;
try {
const { id } = await post(`/sources/new/github`, {
type: 'github',
name: source.name,
htmlUrl: source.htmlUrl.replace(/\/$/, ''),
apiUrl: source.apiUrl.replace(/\/$/, ''),
organization: source.organization
});
const { organization, htmlUrl } = source;
const { fqdn } = settings;
const host = dev
? 'http://localhost:3001'
: fqdn
? fqdn
: `http://${window.location.host}` || '';
const domain = getDomain(fqdn);
let url = 'settings/apps/new';
if (organization) url = `organizations/${organization}/settings/apps/new`;
const name = dashify(domain) || 'app';
const data = JSON.stringify({
name: `coolify-${name}`,
url: host,
hook_attributes: {
url: dev
? 'https://webhook.site/0e5beb2c-4e9b-40e2-a89e-32295e570c21/events'
: `${host}/webhooks/github/events`
},
redirect_url: `${host}/webhooks/github`,
callback_urls: [`${host}/login/github/app`],
public: false,
request_oauth_on_install: false,
setup_url: `${host}/webhooks/github/install?gitSourceId=${id}`,
setup_on_update: true,
default_permissions: {
contents: 'read',
metadata: 'read',
pull_requests: 'read',
emails: 'read'
},
default_events: ['pull_request', 'push']
});
const form = document.createElement('form');
form.setAttribute('method', 'post');
form.setAttribute('action', `${htmlUrl}/${url}?state=${id}`);
const input = document.createElement('input');
input.setAttribute('id', 'manifest');
input.setAttribute('name', 'manifest');
input.setAttribute('type', 'hidden');
input.setAttribute('value', data);
form.appendChild(input);
document.getElementsByTagName('body')[0].appendChild(form);
form.submit();
} catch (error) {
return errorNotification(error);
}
}
</script>
<div class="mx-auto max-w-4xl px-6">
{#if !source.githubAppId}
<form on:submit|preventDefault={newGithubApp} class="py-4">
<div class="flex space-x-1 pb-5 font-bold">
<div class="title">General</div>
</div>
<div class="grid grid-flow-row gap-2 px-10">
<div class="grid grid-flow-row gap-2">
<div class="mt-2 grid grid-cols-2 items-center">
<label for="name" class="text-base font-bold text-stone-100">Name</label>
<input name="name" id="name" required bind:value={source.name} />
</div>
</div>
<div class="grid grid-cols-2 items-center">
<label for="htmlUrl" class="text-base font-bold text-stone-100">HTML URL</label>
<input name="htmlUrl" id="htmlUrl" required bind:value={source.htmlUrl} />
</div>
<div class="grid grid-cols-2 items-center">
<label for="apiUrl" class="text-base font-bold text-stone-100">API URL</label>
<input name="apiUrl" id="apiUrl" required bind:value={source.apiUrl} />
</div>
<div class="grid grid-cols-2">
<div class="flex flex-col">
<label for="organization" class="pt-2 text-base font-bold text-stone-100"
>Organization</label
>
<Explainer
text="Fill it if you would like to use an organization's as your Git Source. Otherwise your user will be used."
/>
</div>
<input
name="organization"
id="organization"
placeholder="eg: coollabsio"
bind:value={source.organization}
/>
</div>
</div>
{#if source.apiUrl && source.htmlUrl && source.name}
<div class="text-center">
<button class=" mt-8 bg-orange-600" type="submit">Create new GitHub App</button>
</div>
{/if}
</form>
{:else if source.githubApp?.installationId}
<form on:submit|preventDefault={handleSubmit} class="py-4">
<div class="flex space-x-1 pb-5 font-bold">
<div class="title">{$t('general')}</div>
{#if $appSession.isAdmin}
<button
type="submit"
class:bg-orange-600={!loading}
class:hover:bg-orange-500={!loading}
disabled={loading}>{loading ? 'Saving...' : 'Save'}</button
>
<button
><a
class="no-underline"
href={`${source.htmlUrl}/apps/${source.githubApp.name}/installations/new`}
>{$t('source.change_app_settings', { name: 'GitHub' })}</a
></button
>
{/if}
</div>
<div class="grid grid-flow-row gap-2 px-10">
<div class="grid grid-flow-row gap-2">
<div class="mt-2 grid grid-cols-2 items-center">
<label for="name" class="text-base font-bold text-stone-100">{$t('forms.name')}</label>
<input name="name" id="name" required bind:value={source.name} />
</div>
</div>
<div class="grid grid-cols-2 items-center">
<label for="htmlUrl" class="text-base font-bold text-stone-100">HTML URL</label>
<input name="htmlUrl" id="htmlUrl" required bind:value={source.htmlUrl} />
</div>
<div class="grid grid-cols-2 items-center">
<label for="apiUrl" class="text-base font-bold text-stone-100">API URL</label>
<input name="apiUrl" id="apiUrl" required bind:value={source.apiUrl} />
</div>
<div class="grid grid-cols-2">
<div class="flex flex-col">
<label for="organization" class="pt-2 text-base font-bold text-stone-100"
>Organization</label
>
</div>
<input
readonly
disabled
name="organization"
id="organization"
placeholder="eg: coollabsio"
bind:value={source.organization}
/>
</div>
</div>
</form>
{:else}
<div class="text-center">
<a href={`${source.htmlUrl}/apps/${source.githubApp.name}/installations/new`}>
<button class=" bg-orange-600 hover:bg-orange-500 mt-8">Install Repositories</button></a
>
</div>
{/if}
</div>

View File

@@ -0,0 +1,284 @@
<script lang="ts">
export let source: any;
export let settings: any;
import Explainer from '$lib/components/Explainer.svelte';
import { page } from '$app/stores';
import { onMount } from 'svelte';
import { post } from '$lib/api';
import { dev } from '$app/env';
import CopyPasswordField from '$lib/components/CopyPasswordField.svelte';
import { toast } from '@zerodevx/svelte-toast';
import { t } from '$lib/translations';
import { errorNotification } from '$lib/common';
import { appSession } from '$lib/store';
import { goto } from '$app/navigation';
const { id } = $page.params;
let url = settings.fqdn ? settings.fqdn : window.location.origin;
if (dev) {
url = `http://localhost:3001`;
}
let loading = false;
let oauthIdEl: HTMLInputElement;
let applicationType: string;
if (!source.gitlabAppId) {
source.gitlabApp = {
oauthId: null,
groupName: null,
appId: null,
appSecret: null
};
}
onMount(() => {
oauthIdEl && oauthIdEl.focus();
});
async function handleSubmit() {
if (loading) return;
loading = true;
if (!source.gitlabAppId) {
// New GitLab App
try {
const { id } = await post(`/sources/new/gitlab`, {
type: 'gitlab',
name: source.name,
htmlUrl: source.htmlUrl.replace(/\/$/, ''),
apiUrl: source.apiUrl.replace(/\/$/, ''),
oauthId: source.gitlabApp.oauthId,
appId: source.gitlabApp.appId,
appSecret: source.gitlabApp.appSecret,
groupName: source.gitlabApp.groupName
});
const from = $page.url.searchParams.get('from');
if (from) {
return window.location.assign(from);
}
return window.location.assign(`/sources/${id}`);
} catch (error) {
return errorNotification(error);
} finally {
loading = false;
}
} else {
// Update GitLab App
try {
await post(`/sources/${id}`, {
name: source.name,
htmlUrl: source.htmlUrl.replace(/\/$/, ''),
apiUrl: source.apiUrl.replace(/\/$/, '')
});
toast.push('Settings saved.');
} catch (error) {
return errorNotification(error);
} finally {
loading = false;
}
}
}
async function changeSettings() {
const {
htmlUrl,
gitlabApp: { oauthId }
} = source;
const left = screen.width / 2 - 1020 / 2;
const top = screen.height / 2 - 1000 / 2;
const newWindow = open(
`${htmlUrl}/oauth/applications/${oauthId}`,
'GitLab',
'resizable=1, scrollbars=1, fullscreen=0, height=1000, width=1020,top=' +
top +
', left=' +
left +
', toolbar=0, menubar=0, status=0'
);
const timer = setInterval(() => {
if (newWindow?.closed) {
clearInterval(timer);
}
}, 100);
}
async function checkOauthId() {
if (source.gitlabApp?.oauthId) {
try {
await post(`/sources/${id}/check`, {
oauthId: source.gitlabApp?.oauthId
});
} catch ({ error }) {
source.gitlabApp.oauthId = null;
oauthIdEl.focus();
return errorNotification(error);
}
}
}
function newApp() {
switch (applicationType) {
case 'user':
window.open(`${source.htmlUrl}/-/profile/applications`);
break;
case 'group':
window.open(
`${source.htmlUrl}/groups/${source.gitlabApp.groupName}/-/settings/applications`
);
break;
case 'instance':
break;
default:
break;
}
}
</script>
<div class="mx-auto max-w-4xl px-6">
<form on:submit|preventDefault={handleSubmit} class="py-4">
<div class="flex space-x-1 pb-7 font-bold">
<div class="title">General</div>
{#if $appSession.isAdmin}
<button
type="submit"
class:bg-orange-600={!loading}
class:hover:bg-orange-500={!loading}
disabled={loading}>{loading ? $t('forms.saving') : $t('forms.save')}</button
>
{#if source.gitlabAppId}
<button on:click|preventDefault={changeSettings}
>{$t('source.change_app_settings', { name: 'GitLab' })}</button
>
{/if}
{/if}
</div>
<div class="grid grid-flow-row gap-2 px-10">
{#if !source.gitlabAppId}
<div class="grid grid-cols-2 items-center">
<label for="type" class="text-base font-bold text-stone-100">Application Type</label>
<select name="type" id="type" class="w-96" bind:value={applicationType}>
<option value="user">{$t('source.gitlab.user_owned')}</option>
<option value="group">{$t('source.gitlab.group_owned')}</option>
{#if source.htmlUrl !== 'https://gitlab.com'}
<option value="instance">{$t('source.gitlab.self_hosted')}</option>
{/if}
</select>
</div>
{#if applicationType === 'group'}
<div class="grid grid-cols-2 items-center">
<label for="groupName" class="text-base font-bold text-stone-100">Group Name</label>
<input
name="groupName"
id="groupName"
required
bind:value={source.gitlabApp.groupName}
/>
</div>
{/if}
{/if}
<div class="grid grid-flow-row gap-2">
<div class="mt-2 grid grid-cols-2 items-center">
<label for="name" class="text-base font-bold text-stone-100">{$t('forms.name')}</label>
<input name="name" id="name" required bind:value={source.name} />
</div>
</div>
{#if source.gitlabApp.groupName}
<div class="grid grid-cols-2 items-center">
<label for="groupName" class="text-base font-bold text-stone-100"
>{$t('source.group_name')}</label
>
<input
name="groupName"
id="groupName"
disabled={source.gitlabAppId}
readonly={source.gitlabAppId}
required
bind:value={source.gitlabApp.groupName}
/>
</div>
{/if}
<div class="grid grid-cols-2 items-center">
<label for="htmlUrl" class="text-base font-bold text-stone-100">HTML URL</label>
<input
name="htmlUrl"
id="htmlUrl"
required
disabled={source.gitlabAppId}
readonly={source.gitlabAppId}
value={source.htmlUrl}
/>
</div>
<div class="grid grid-cols-2 items-center">
<label for="apiUrl" class="text-base font-bold text-stone-100">API URL</label>
<input
name="apiUrl"
id="apiUrl"
disabled={source.gitlabAppId}
readonly={source.gitlabAppId}
required
value={source.apiUrl}
/>
</div>
<div class="grid grid-cols-2 items-start">
<div class="flex-col">
<label for="oauthId" class="pt-2 text-base font-bold text-stone-100"
>{$t('source.oauth_id')}</label
>
{#if !source.gitlabAppId}
<Explainer text={$t('source.oauth_id_explainer')} />
{/if}
</div>
<input
disabled={source.gitlabAppId}
readonly={source.gitlabAppId}
on:change={checkOauthId}
bind:this={oauthIdEl}
name="oauthId"
id="oauthId"
type="number"
required
bind:value={source.gitlabApp.oauthId}
/>
</div>
<div class="grid grid-cols-2 items-center">
<label for="appId" class="text-base font-bold text-stone-100"
>{$t('source.application_id')}</label
>
<input
name="appId"
id="appId"
disabled={source.gitlabAppId}
readonly={source.gitlabAppId}
required
bind:value={source.gitlabApp.appId}
/>
</div>
<div class="grid grid-cols-2 items-center">
<label for="appSecret" class="text-base font-bold text-stone-100"
>{$t('index.secret')}</label
>
<CopyPasswordField
disabled={source.gitlabAppId}
readonly={source.gitlabAppId}
isPasswordField={true}
name="appSecret"
id="appSecret"
required
bind:value={source.gitlabApp.appSecret}
/>
</div>
</div>
</form>
{#if !source.gitlabAppId}
<Explainer
customClass="w-full"
text="<span class='font-bold text-base text-white'>Scopes required:</span>
<br>- <span class='text-orange-500 font-bold'>api</span> (Access the authenticated user's API)
<br>- <span class='text-orange-500 font-bold'>read_repository</span> (Allows read-only access to the repository)
<br>- <span class='text-orange-500 font-bold'>email</span> (Allows read-only access to the user's primary email address using OpenID Connect)
<br>
<br>For extra security, you can set <span class='text-orange-500 font-bold'>Expire Access Tokens</span>
<br><br>Webhook URL: <span class='text-orange-500 font-bold'>{url}/webhooks/gitlab</span>"
/>
{/if}
</div>

View File

@@ -0,0 +1,62 @@
<script lang="ts">
export let source: any;
export let settings: any;
import Github from './_Github.svelte';
import Gitlab from './_Gitlab.svelte';
function setPredefined(type: string) {
switch (type) {
case 'github':
source.name = 'Github.com';
source.type = 'github';
source.htmlUrl = 'https://github.com';
source.apiUrl = 'https://api.github.com';
source.organization = undefined;
break;
case 'gitlab':
source.name = 'Gitlab.com';
source.type = 'gitlab';
source.htmlUrl = 'https://gitlab.com';
source.apiUrl = 'https://gitlab.com/api';
source.organization = undefined;
break;
case 'bitbucket':
source.name = 'Bitbucket.com';
source.type = 'bitbucket';
source.htmlUrl = 'https://bitbucket.com';
source.apiUrl = 'https://api.bitbucket.org';
source.organization = undefined;
break;
default:
break;
}
}
</script>
<div class="flex h-20 items-center space-x-2 p-5 px-6 font-bold">
<div class="-mb-1 flex-col">
<div class="md:max-w-64 truncate text-base tracking-tight md:text-2xl lg:block">
New Git Source
</div>
</div>
</div>
<div class="flex flex-col justify-center">
<div class="flex-col space-y-2 pb-10 text-center">
<div class="text-xl font-bold text-white">Select a provider</div>
<div class="flex justify-center space-x-2">
<button class="w-32" on:click={() => setPredefined('github')}>GitHub.com</button>
<button class="w-32" on:click={() => setPredefined('gitlab')}>GitLab.com</button>
</div>
</div>
{#if source?.type}
<div>
{#if source.type === 'github'}
<Github bind:source {settings} />
{:else if source.type === 'gitlab'}
<Gitlab bind:source {settings} />
{/if}
</div>
{/if}
</div>

View File

@@ -0,0 +1,58 @@
<script lang="ts">
import Github from './_Github.svelte';
import Gitlab from './_Gitlab.svelte';
export let source: any;
export let settings: any;
</script>
<div class="flex h-20 items-center space-x-2 p-5 px-6 font-bold">
<div class="-mb-5 flex-col">
<div class="md:max-w-64 truncate text-base tracking-tight md:text-2xl lg:block">
Configuration
</div>
<span class="text-xs">{source.name}</span>
</div>
{#if source?.type === 'gitlab'}
<svg viewBox="0 0 128 128" class="w-8">
<path
fill="#FC6D26"
d="M126.615 72.31l-7.034-21.647L105.64 7.76c-.716-2.206-3.84-2.206-4.556 0l-13.94 42.903H40.856L26.916 7.76c-.717-2.206-3.84-2.206-4.557 0L8.42 50.664 1.385 72.31a4.792 4.792 0 001.74 5.358L64 121.894l60.874-44.227a4.793 4.793 0 001.74-5.357"
/><path fill="#E24329" d="M64 121.894l23.144-71.23H40.856L64 121.893z" /><path
fill="#FC6D26"
d="M64 121.894l-23.144-71.23H8.42L64 121.893z"
/><path
fill="#FCA326"
d="M8.42 50.663L1.384 72.31a4.79 4.79 0 001.74 5.357L64 121.894 8.42 50.664z"
/><path
fill="#E24329"
d="M8.42 50.663h32.436L26.916 7.76c-.717-2.206-3.84-2.206-4.557 0L8.42 50.664z"
/><path fill="#FC6D26" d="M64 121.894l23.144-71.23h32.437L64 121.893z" /><path
fill="#FCA326"
d="M119.58 50.663l7.035 21.647a4.79 4.79 0 01-1.74 5.357L64 121.894l55.58-71.23z"
/><path
fill="#E24329"
d="M119.58 50.663H87.145l13.94-42.902c.717-2.206 3.84-2.206 4.557 0l13.94 42.903z"
/>
</svg>
{:else if source?.type === 'github'}
<svg viewBox="0 0 128 128" class="w-8">
<g fill="#ffffff"
><path
fill-rule="evenodd"
clip-rule="evenodd"
d="M64 5.103c-33.347 0-60.388 27.035-60.388 60.388 0 26.682 17.303 49.317 41.297 57.303 3.017.56 4.125-1.31 4.125-2.905 0-1.44-.056-6.197-.082-11.243-16.8 3.653-20.345-7.125-20.345-7.125-2.747-6.98-6.705-8.836-6.705-8.836-5.48-3.748.413-3.67.413-3.67 6.063.425 9.257 6.223 9.257 6.223 5.386 9.23 14.127 6.562 17.573 5.02.542-3.903 2.107-6.568 3.834-8.076-13.413-1.525-27.514-6.704-27.514-29.843 0-6.593 2.36-11.98 6.223-16.21-.628-1.52-2.695-7.662.584-15.98 0 0 5.07-1.623 16.61 6.19C53.7 35 58.867 34.327 64 34.304c5.13.023 10.3.694 15.127 2.033 11.526-7.813 16.59-6.19 16.59-6.19 3.287 8.317 1.22 14.46.593 15.98 3.872 4.23 6.215 9.617 6.215 16.21 0 23.194-14.127 28.3-27.574 29.796 2.167 1.874 4.097 5.55 4.097 11.183 0 8.08-.07 14.583-.07 16.572 0 1.607 1.088 3.49 4.148 2.897 23.98-7.994 41.263-30.622 41.263-57.294C124.388 32.14 97.35 5.104 64 5.104z"
/><path
d="M26.484 91.806c-.133.3-.605.39-1.035.185-.44-.196-.685-.605-.543-.906.13-.31.603-.395 1.04-.188.44.197.69.61.537.91zm2.446 2.729c-.287.267-.85.143-1.232-.28-.396-.42-.47-.983-.177-1.254.298-.266.844-.14 1.24.28.394.426.472.984.17 1.255zM31.312 98.012c-.37.258-.976.017-1.35-.52-.37-.538-.37-1.183.01-1.44.373-.258.97-.025 1.35.507.368.545.368 1.19-.01 1.452zm3.261 3.361c-.33.365-1.036.267-1.552-.23-.527-.487-.674-1.18-.343-1.544.336-.366 1.045-.264 1.564.23.527.486.686 1.18.333 1.543zm4.5 1.951c-.147.473-.825.688-1.51.486-.683-.207-1.13-.76-.99-1.238.14-.477.823-.7 1.512-.485.683.206 1.13.756.988 1.237zm4.943.361c.017.498-.563.91-1.28.92-.723.017-1.308-.387-1.315-.877 0-.503.568-.91 1.29-.924.717-.013 1.306.387 1.306.88zm4.598-.782c.086.485-.413.984-1.126 1.117-.7.13-1.35-.172-1.44-.653-.086-.498.422-.997 1.122-1.126.714-.123 1.354.17 1.444.663zm0 0"
/></g
>
</svg>
{/if}
</div>
<div>
{#if source.type === 'github'}
<Github bind:source {settings} />
{:else if source.type === 'gitlab'}
<Gitlab bind:source {settings} />
{/if}
</div>

View File

@@ -0,0 +1,70 @@
<script context="module" lang="ts">
import type { Load } from '@sveltejs/kit';
export const load: Load = async ({ fetch, url, params }) => {
try {
const { id } = params;
const response = await get(`/sources/${id}`);
const { source, settings } = response;
if (id !== 'new' && (!source || Object.entries(source).length === 0)) {
return {
status: 302,
redirect: '/sources'
};
}
return {
props: {
source
},
stuff: {
source,
settings
}
};
} catch (error) {
return handlerNotFoundLoad(error, url);
}
};
</script>
<script lang="ts">
export let source: any;
import { del, get } from '$lib/api';
import { page } from '$app/stores';
import { errorNotification, handlerNotFoundLoad } from '$lib/common';
import { t } from '$lib/translations';
import { appSession } from '$lib/store';
import DeleteIcon from '$lib/components/DeleteIcon.svelte';
import { goto } from '$app/navigation';
const { id } = $page.params;
async function deleteSource(name: string) {
const sure = confirm($t('application.confirm_to_delete', { name }));
if (sure) {
try {
await del(`/sources/${id}`, {});
await goto('/sources', { replaceState: true });
} catch (error) {
errorNotification(error);
}
}
}
</script>
{#if id !== 'new'}
<nav class="nav-side">
<button
on:click={() => deleteSource(source.name)}
title={$t('source.delete_git_source')}
type="submit"
disabled={!$appSession.isAdmin}
class:hover:text-red-500={$appSession.isAdmin}
class="icons tooltip-bottom bg-transparent text-sm"
data-tooltip={$appSession.isAdmin
? $t('source.delete_git_source')
: $t('source.permission_denied')}><DeleteIcon /></button
>
</nav>
{/if}
<slot />

View File

@@ -0,0 +1,24 @@
<script context="module" lang="ts">
import type { Load } from '@sveltejs/kit';
export const load: Load = async ({ fetch, params, stuff }) => {
return {
props: { ...stuff }
};
};
</script>
<script lang="ts">
export let source: any;
export let settings: any;
import { page } from '$app/stores';
import Source from './_Source.svelte';
import New from './_New.svelte';
const { id } = $page.params;
</script>
{#if id === 'new'}
<New bind:source bind:settings />
{:else}
<Source bind:source bind:settings />
{/if}

View File

@@ -0,0 +1,159 @@
<script context="module" lang="ts">
import type { Load } from '@sveltejs/kit';
export const load: Load = async () => {
try {
const response = await get(`/sources`);
return {
props: {
...response
}
};
} catch (error: any) {
return {
status: 500,
error: new Error(error)
};
}
};
</script>
<script lang="ts">
export let sources: any = [];
import { get, post } from '$lib/api';
import { goto } from '$app/navigation';
import { getDomain } from '$lib/common';
import { t } from '$lib/translations';
import { appSession } from '$lib/store';
const ownSources = sources.filter((source: { teams: { id: any }[] }) => {
if (source.teams[0].id === $appSession.teamId) {
return source;
}
});
const otherSources = sources.filter((source: any) => {
if (source.teams[0].id !== $appSession.teamId) {
return source;
}
});
</script>
<div class="flex space-x-1 p-6 font-bold">
<div class="mr-4 text-2xl tracking-tight">{$t('index.git_sources')}</div>
{#if $appSession.isAdmin}
<a href="/sources/new" class="add-icon bg-orange-600 hover:bg-orange-500">
<svg
class="w-6"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
><path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 6v6m0 0v6m0-6h6m-6 0H6"
/></svg
>
</a>
{/if}
</div>
<div class="flex-col justify-center">
{#if !sources || ownSources.length === 0}
<div class="flex-col">
<div class="text-center text-xl font-bold">{$t('source.no_git_sources_found')}</div>
</div>
{/if}
{#if ownSources.length > 0 || otherSources.length > 0}
<div class="flex flex-col">
<div class="flex flex-col flex-wrap justify-center px-2 md:flex-row">
{#each ownSources as source}
<a href="/sources/{source.id}" class="w-96 p-2 no-underline">
<div
class="box-selection group relative hover:bg-orange-600"
class:border-red-500={source.gitlabApp && !source.gitlabAppId}
class:border-0={source.gitlabApp && !source.gitlabAppId}
class:border-l-4={source.gitlabApp && !source.gitlabAppId}
>
<div class="absolute top-0 left-0 -m-5 h-10 w-10">
{#if source?.type === 'gitlab'}
<svg viewBox="0 0 128 128">
<path
fill="#FC6D26"
d="M126.615 72.31l-7.034-21.647L105.64 7.76c-.716-2.206-3.84-2.206-4.556 0l-13.94 42.903H40.856L26.916 7.76c-.717-2.206-3.84-2.206-4.557 0L8.42 50.664 1.385 72.31a4.792 4.792 0 001.74 5.358L64 121.894l60.874-44.227a4.793 4.793 0 001.74-5.357"
/><path fill="#E24329" d="M64 121.894l23.144-71.23H40.856L64 121.893z" /><path
fill="#FC6D26"
d="M64 121.894l-23.144-71.23H8.42L64 121.893z"
/><path
fill="#FCA326"
d="M8.42 50.663L1.384 72.31a4.79 4.79 0 001.74 5.357L64 121.894 8.42 50.664z"
/><path
fill="#E24329"
d="M8.42 50.663h32.436L26.916 7.76c-.717-2.206-3.84-2.206-4.557 0L8.42 50.664z"
/><path fill="#FC6D26" d="M64 121.894l23.144-71.23h32.437L64 121.893z" /><path
fill="#FCA326"
d="M119.58 50.663l7.035 21.647a4.79 4.79 0 01-1.74 5.357L64 121.894l55.58-71.23z"
/><path
fill="#E24329"
d="M119.58 50.663H87.145l13.94-42.902c.717-2.206 3.84-2.206 4.557 0l13.94 42.903z"
/>
</svg>
{:else if source?.type === 'github'}
<svg viewBox="0 0 128 128">
<g fill="#ffffff"
><path
fill-rule="evenodd"
clip-rule="evenodd"
d="M64 5.103c-33.347 0-60.388 27.035-60.388 60.388 0 26.682 17.303 49.317 41.297 57.303 3.017.56 4.125-1.31 4.125-2.905 0-1.44-.056-6.197-.082-11.243-16.8 3.653-20.345-7.125-20.345-7.125-2.747-6.98-6.705-8.836-6.705-8.836-5.48-3.748.413-3.67.413-3.67 6.063.425 9.257 6.223 9.257 6.223 5.386 9.23 14.127 6.562 17.573 5.02.542-3.903 2.107-6.568 3.834-8.076-13.413-1.525-27.514-6.704-27.514-29.843 0-6.593 2.36-11.98 6.223-16.21-.628-1.52-2.695-7.662.584-15.98 0 0 5.07-1.623 16.61 6.19C53.7 35 58.867 34.327 64 34.304c5.13.023 10.3.694 15.127 2.033 11.526-7.813 16.59-6.19 16.59-6.19 3.287 8.317 1.22 14.46.593 15.98 3.872 4.23 6.215 9.617 6.215 16.21 0 23.194-14.127 28.3-27.574 29.796 2.167 1.874 4.097 5.55 4.097 11.183 0 8.08-.07 14.583-.07 16.572 0 1.607 1.088 3.49 4.148 2.897 23.98-7.994 41.263-30.622 41.263-57.294C124.388 32.14 97.35 5.104 64 5.104z"
/><path
d="M26.484 91.806c-.133.3-.605.39-1.035.185-.44-.196-.685-.605-.543-.906.13-.31.603-.395 1.04-.188.44.197.69.61.537.91zm2.446 2.729c-.287.267-.85.143-1.232-.28-.396-.42-.47-.983-.177-1.254.298-.266.844-.14 1.24.28.394.426.472.984.17 1.255zM31.312 98.012c-.37.258-.976.017-1.35-.52-.37-.538-.37-1.183.01-1.44.373-.258.97-.025 1.35.507.368.545.368 1.19-.01 1.452zm3.261 3.361c-.33.365-1.036.267-1.552-.23-.527-.487-.674-1.18-.343-1.544.336-.366 1.045-.264 1.564.23.527.486.686 1.18.333 1.543zm4.5 1.951c-.147.473-.825.688-1.51.486-.683-.207-1.13-.76-.99-1.238.14-.477.823-.7 1.512-.485.683.206 1.13.756.988 1.237zm4.943.361c.017.498-.563.91-1.28.92-.723.017-1.308-.387-1.315-.877 0-.503.568-.91 1.29-.924.717-.013 1.306.387 1.306.88zm4.598-.782c.086.485-.413.984-1.126 1.117-.7.13-1.35-.172-1.44-.653-.086-.498.422-.997 1.122-1.126.714-.123 1.354.17 1.444.663zm0 0"
/></g
>
</svg>
{/if}
</div>
<div class="truncate text-center text-xl font-bold">{source.name}</div>
{#if $appSession.teamId === '0' && otherSources.length > 0}
<div class="truncate text-center">{source.teams[0].name}</div>
{/if}
{#if (source.type === 'gitlab' && !source.gitlabAppId) || (source.type === 'github' && source.githubApp?.installationId === null)}
<div class="truncate text-center font-bold text-red-500 group-hover:text-white">
{$t('application.configuration.configuration_missing')}
</div>
{:else}
<div class="truncate text-center">{getDomain(source.htmlUrl) || ''}</div>
{/if}
</div>
</a>
{/each}
</div>
{#if otherSources.length > 0 && $appSession.teamId === '0'}
<div class="px-6 pb-5 pt-10 text-xl font-bold">Other Sources</div>
<div class="flex flex-col flex-wrap justify-center px-2 md:flex-row">
{#each otherSources as source}
<a href="/sources/{source.id}" class="w-96 p-2 no-underline">
<div
class="box-selection group hover:bg-orange-600"
class:border-red-500={source.gitlabApp && !source.gitlabAppId}
class:border-0={source.gitlabApp && !source.gitlabAppId}
class:border-l-4={source.gitlabApp && !source.gitlabAppId}
>
<div class="truncate text-center text-xl font-bold">{source.name}</div>
{#if $appSession.teamId === '0'}
<div class="truncate text-center">{source.teams[0].name}</div>
{/if}
{#if (source.type === 'gitlab' && !source.gitlabAppId) || (source.type === 'github' && source.githubApp?.installationId === null)}
<div class="truncate text-center font-bold text-red-500 group-hover:text-white">
{$t('application.configuration.configuration_missing')}
</div>
{:else}
<div class="truncate text-center">{source.htmlUrl}</div>
{/if}
</div>
</a>
{/each}
</div>
{/if}
</div>
{/if}
</div>