Skip to content

Commit

Permalink
Repo module (#1517)
Browse files Browse the repository at this point in the history
Co-authored-by: Gašper Grom <[email protected]>
  • Loading branch information
gaspergrom and Gašper Grom authored Sep 25, 2023
1 parent 70c83e8 commit f949005
Show file tree
Hide file tree
Showing 8 changed files with 370 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
<template>
<slot :connect="connect" />
<slot :connect="connect" :has-settings="true" :settings-component="GithubSettings" />
</template>

<script setup>
import { computed } from 'vue';
import config from '@/config';
import ConfirmDialog from '@/shared/dialog/confirm-dialog';
import { useRouter } from 'vue-router';
import GithubSettings from './github-settings.vue';
defineProps({
integration: {
Expand Down
262 changes: 262 additions & 0 deletions frontend/src/integrations/github/components/github-settings-drawer.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
<template>
<app-drawer
v-model="isDrawerVisible"
title="GitHub"
size="600px"
pre-title="Integration"
:show-footer="true"
has-border
@close="isDrawerVisible = false"
>
<template #beforeTitle>
<img
:src="githubDetails.image"
class="w-6 h-6 mr-2"
alt="GitHub logo"
/>
</template>
<template #content>
<div>
<!-- Connected organization info -->
<section v-if="owner" class="border border-gray-200 rounded-md py-4 px-5 mb-6">
<p class="text-2xs font-medium text-gray-400 mb-1">
Connected organization
</p>
<div class="flex items-center">
<div v-if="owner.logo" class="h-5 w-5 rounded border border-gray-200 mr-2">
<img :src="owner.logo" class="object-cover" :alt="owner.logo">
</div>
<p class="text-xs font-medium leading-5">
{{ owner.name }}
</p>
</div>
</section>

<!-- Disclaimer -->
<section class="pb-4">
<div class="pb-4">
<h6 class="text-sm font-medium leading-5 mb-2">
Repository mapping
</h6>
<p class="text-2xs leading-4.5 text-gray-500">
Select the subproject you want to map with each connected repository.
</p>
</div>
<div class="border border-yellow-100 rounded-md bg-yellow-50 p-2 flex">
<div class="w-4 h-4 flex items-center ri-alert-fill text-yellow-500" />
<div class="flex-grow text-yellow-900 text-2xs leading-4.5 pl-2">
Repository mapping is not reversible. Once GitHub is connected,
you won’t be able to update these settings and reconnecting a different organization or repositories won’t override past activities.
</div>
</div>
</section>

<!-- Repository mapping -->
<section>
<div class="flex border-b border-gray-200 items-center h-8">
<div class="w-1/2 pr-4">
<p class="text-3xs uppercase text-gray-400 font-semibold tracking-1">
REPOSITORY
</p>
</div>
<div class="w-1/2 pr-4">
<p class="text-3xs uppercase text-gray-400 font-semibold tracking-1">
SUB-PROJECT
</p>
</div>
</div>
<div class="py-1.5">
<article v-for="repo of repos" :key="repo.url" class="py-1.5 flex items-center">
<div class="w-1/2 flex items-center pr-4">
<i class="ri-git-repository-line text-base mr-2" />
<p class="text-2xs leading-5 flex-grow truncate">
/{{ repo.name }}
</p>
</div>
<div class="w-1/2">
<app-form-item
:validation="$v[repo.url]"
:error-messages="{
required: 'This field is required',
}"
class="mb-0"
error-class="relative top-0"
>
<el-select
v-model="form[repo.url]"
placeholder="Select sub-project"
class="w-full"
placement="bottom-end"
filterable
@blur="$v[repo.url].$touch"
@change="$v[repo.url].$touch"
>
<el-option
v-for="subproject of subprojects"
:key="subproject.id"
:value="subproject.id"
:label="subproject.name"
/>
</el-select>
</app-form-item>
</div>
</article>
</div>
</section>
</div>
</template>

<template #footer>
<div style="flex: auto">
<el-button
class="btn btn--md btn--bordered mr-3"
@click="isDrawerVisible = false"
>
Cancel
</el-button>
<el-button
type="primary"
class="btn btn--md btn--primary"
:disabled="sending || $v.$invalid"
:loading="sending"
@click="connect()"
>
Connect
</el-button>
</div>
</template>
</app-drawer>
</template>

<script lang="ts" setup>
import {
computed, onMounted, reactive,
ref,
} from 'vue';
import Message from '@/shared/message/message';
import { CrowdIntegrations } from '@/integrations/integrations-config';
import { LfService } from '@/modules/lf/segments/lf-segments-service';
import { useRoute, useRouter } from 'vue-router';
import { required } from '@vuelidate/validators';
import useVuelidate from '@vuelidate/core';
import AppFormItem from '@/shared/form/form-item.vue';
import { IntegrationService } from '@/modules/integration/integration-service';
import ConfirmDialog from '@/shared/dialog/confirm-dialog';
import { mapActions } from '@/shared/vuex/vuex.helpers';
const props = defineProps<{
modelValue: boolean,
integration: any
}>();
const emit = defineEmits<{(e: 'update:modelValue', value: boolean): void }>();
const route = useRoute();
const router = useRouter();
// Store
const { doFetch } = mapActions('integration');
// Drawer visibility
const isDrawerVisible = computed({
get() {
return props.modelValue;
},
set(val) {
emit('update:modelValue', val);
},
});
// Display data
const repos = computed(() => props.integration?.settings?.repos || []);
const owner = computed<{name: string, logo?: string} | null>(() => (repos.value.length > 0 ? {
name: repos.value[0].owner,
logo: props.integration?.settings?.orgAvatar,
} : null));
// Static github details
const githubDetails = computed(() => CrowdIntegrations.getConfig('github'));
// Form
const form = reactive<Record<string, string>>(repos.value.reduce((a: Record<string, any>, b: any) => ({
...a,
[b.url]: props.integration.segmentId,
}), {}));
const rules = computed(() => repos.value.reduce((a: Record<string, any>, b: any) => ({
...a,
[b.url]: {
required,
},
}), {}));
const $v = useVuelidate(rules, form);
// Connecting
const sending = ref(false);
const connect = () => {
const data = { ...form };
ConfirmDialog({
type: 'warning',
title: 'Are you sure you want to proceed?',
message:
'Repository mapping is not reversible. Once GitHub is connected, you wont be able to update these settings.\n\n'
+ 'Reconnecting a different organization and/or repositories won’t remove past activities. '
+ 'In order to clean up existing data please reach out to our support team.',
confirmButtonText: 'Connect GitHub',
cancelButtonText: 'Cancel',
icon: 'ri-alert-fill',
} as any)
.then(() => {
IntegrationService.githubMapRepos(props.integration.id, data, [props.integration.segmentId])
.then(() => {
isDrawerVisible.value = false;
doFetch([props.integration.segmentId]);
Message.success(
'The first activities will show up in a couple of seconds. <br /> '
+ '<br /> This process might take a few minutes to finish, depending on the amount of data.',
{
title: 'GitHub integration created successfully',
},
);
router.push({
name: 'integration',
params: {
id: props.integration.segmentId,
},
});
})
.catch(() => {
Message.error(
'There was an error mapping github repos',
);
});
});
};
// Fetching subprojects
const subprojects = ref([]);
const fetchSubProjects = () => {
LfService.findSegment(route.params.grandparentId)
.then((segment) => {
subprojects.value = segment.projects.map((p) => p.subprojects).flat();
});
};
onMounted(() => {
fetchSubProjects();
});
</script>

<script lang="ts">
export default {
name: 'AppGithubSettingsDrawer',
};
</script>
71 changes: 71 additions & 0 deletions frontend/src/integrations/github/components/github-settings.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<template>
<div>
<el-button
v-if="props.integration?.status === 'mapping'"
class="btn btn-link btn-link--md btn-link--primary"
@click="settingsDrawerOpen = true"
>
<i class="ri-settings-2-line mr-2" />Settings
</el-button>
<el-popover v-else trigger="hover" placement="top" popper-class="!w-auto">
<template #reference>
<div
class="text-gray-500 text-2xs flex items-center leading-4"
>
<i class="ri-git-repository-line text-base !text-gray-400 mr-1 h-4 flex items-center" />
{{ Object.keys(mappings).length }} {{ Object.keys(mappings).length !== 1 ? 'repositories' : 'repository' }}
</div>
</template>
<div class="-my-1 px-1 max-h-44 overflow-auto">
<article v-for="mapping of mappings" :key="mapping.url" class="py-2 flex items-center flex-nowrap">
<div class="ri-git-repository-line text-base mr-2 h-4 flex items-center" />
<div class="text-xs leading-5 max-w-3xs truncate">
/{{ repoNameFromUrl(mapping.url) }}
</div>
<div class="ri-arrow-right-line text-gray-400 text-base mx-2 h-4 flex items-center" />
<div class="text-xs leading-5 max-w-3xs truncate">
{{ mapping.segment.name }}
</div>
</article>
</div>
</el-popover>
</div>
<app-github-settings-drawer v-if="settingsDrawerOpen" v-model="settingsDrawerOpen" :integration="props.integration" />
</template>
<script setup>
import { onMounted, ref } from 'vue';
import AppGithubSettingsDrawer from '@/integrations/github/components/github-settings-drawer.vue';
import { IntegrationService } from '@/modules/integration/integration-service';
const props = defineProps({
integration: {
type: Object,
default: () => {},
},
});
const settingsDrawerOpen = ref(props.integration.status === 'mapping');
const mappings = ref([]);
const repoNameFromUrl = (url) => url.split('/').at(-1);
onMounted(() => {
if (props.integration.status !== 'mapping') {
IntegrationService.fetchGitHubMappings(props.integration)
.then((res) => {
mappings.value = res;
});
}
});
</script>
<script>
export default {
name: 'AppGithubSettings',
};
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@
#default="{
connect,
settings,
settingsComponent,
hasSettings,
hasIntegration,
}"
>
<slot
:connect="connect"
:settings="settings"
:settings-component="settingsComponent"
:has-settings="hasSettings"
:has-integration="hasIntegration"
:connected="isConnected"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
connected,
settings,
hasSettings,
settingsComponent,
hasIntegration,
}"
>
Expand All @@ -99,8 +100,9 @@
>
Disconnect
</el-button>
<component :is="settingsComponent" v-if="connected && hasSettings && settingsComponent" :integration="integration" />
<el-button
v-if="connected && hasSettings"
v-else-if="connected && hasSettings"
class="btn btn-link btn-link--md btn-link--primary"
@click="settings"
>
Expand Down Expand Up @@ -165,7 +167,7 @@ const isError = computed(
const isNoData = computed(() => props.integration.status === 'no-data');
const isWaitingForAction = computed(
() => props.integration.status === 'pending-action',
() => ['pending-action', 'mapping'].includes(props.integration.status),
);
const isWaitingApproval = computed(
Expand Down
Loading

0 comments on commit f949005

Please sign in to comment.