Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f2e883d

Browse files
modify DashboardRepoList component to show DashboardRepoGroup instead of flat repo list
1 parent 0923458 commit f2e883d

File tree

1 file changed

+126
-40
lines changed

1 file changed

+126
-40
lines changed

‎web_src/js/components/DashboardRepoList.vue

Lines changed: 126 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,74 @@
11
<script lang="ts">
2-
import {nextTick, defineComponent} from 'vue';
2+
import {nextTick, defineComponent, computed, ref, typeRef} from 'vue';
33
import {SvgIcon} from '../svg.ts';
44
import {GET} from '../modules/fetch.ts';
55
import {fomanticQuery} from '../modules/fomantic/base.ts';
6+
import DashboardRepoGroup from './DashboardRepoGroup.vue';
67
78
const {appSubUrl, assetUrlPrefix, pageData} = window.config;
89
9-
type CommitStatus = 'pending' | 'success' | 'error' | 'failure' | 'warning' | 'skipped';
10+
exporttype CommitStatus = 'pending' | 'success' | 'error' | 'failure' | 'warning' | 'skipped';
1011
11-
type CommitStatusMap = {
12-
[status in CommitStatus]: {
12+
exporttype CommitStatusMap = {
13+
[status in CommitStatus]: {
1314
name: string,
1415
color: string,
1516
};
1617
};
1718
1819
// make sure this matches templates/repo/commit_status.tmpl
19-
const commitStatus: CommitStatusMap = {
20+
exportconst commitStatus: CommitStatusMap = {
2021
pending: {name: 'octicon-dot-fill', color: 'yellow'},
2122
success: {name: 'octicon-check', color: 'green'},
2223
error: {name: 'gitea-exclamation', color: 'red'},
2324
failure: {name: 'octicon-x', color: 'red'},
2425
warning: {name: 'gitea-exclamation', color: 'yellow'},
2526
skipped: {name: 'octicon-skip', color: 'grey'},
2627
};
27-
28+
export type GroupMapType = {
29+
repos: any[]
30+
subgroups: number[]
31+
id: number
32+
[ k: string ]: any
33+
}
2834
export default defineComponent({
29-
components: {SvgIcon},
35+
components: {SvgIcon, DashboardRepoGroup},
36+
provide() {
37+
return {
38+
expandedGroups: computed({
39+
get: () => {
40+
return this.expandedGroups;
41+
},
42+
set: (v) => {
43+
this.expandedGroups = v;
44+
},
45+
}),
46+
searchURL: this.searchURL,
47+
groups: computed({
48+
get: () => {
49+
return this.groups;
50+
},
51+
set: (v) => {
52+
this.groups = v;
53+
},
54+
}),
55+
repos: computed(() => this.computedRepos),
56+
loadedMap: computed({
57+
get: () => {
58+
return this.loadedMap;
59+
},
60+
set: (v) => {
61+
this.loadedMap = v;
62+
},
63+
}),
64+
orgName: this.organizationName,
65+
};
66+
},
67+
setup() {
68+
const groups = ref(new Map<number, GroupMapType>());
69+
const loadedMap = ref(new Map<number, boolean>([[0, true]]));
70+
return {groupsRef: groups, loadedRef: loadedMap};
71+
},
3072
data() {
3173
const params = new URLSearchParams(window.location.search);
3274
const tab = params.get('repo-search-tab') || 'repos';
@@ -39,6 +81,7 @@ export default defineComponent({
3981
return {
4082
tab,
4183
repos: [],
84+
groupData: this.groupsRef,
4285
reposTotalCount: null,
4386
reposFilter,
4487
archivedFilter,
@@ -78,15 +121,15 @@ export default defineComponent({
78121
subUrl: appSubUrl,
79122
...pageData.dashboardRepoList,
80123
activeIndex: -1, // don't select anything at load, first cursor down will select
124+
expandedGroupsRaw: [],
81125
};
82126
},
83-
84127
computed: {
85128
showMoreReposLink() {
86129
return this.repos.length > 0 && this.repos.length < this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`];
87130
},
88131
searchURL() {
89-
return `${this.subUrl}/repo/search?sort=updated&order=desc&uid=${this.uid}&team_id=${this.teamId}&q=${this.searchQuery
132+
return `${this.subUrl}/group/search?sort=updated&order=desc&uid=${this.uid}&team_id=${this.teamId}&q=${this.searchQuery
90133
}&page=${this.page}&limit=${this.searchLimit}&mode=${this.repoTypes[this.reposFilter].searchMode
91134
}${this.archivedFilter === 'archived' ? '&archived=true' : ''}${this.archivedFilter === 'unarchived' ? '&archived=false' : ''
92135
}${this.privateFilter === 'private' ? '&is_private=true' : ''}${this.privateFilter === 'public' ? '&is_private=false' : ''
@@ -107,6 +150,38 @@ export default defineComponent({
107150
checkboxPrivateFilterProps() {
108151
return {checked: this.privateFilter === 'private', indeterminate: this.privateFilter === 'both'};
109152
},
153+
expandedGroups: {
154+
get() {
155+
return this.expandedGroupsRaw;
156+
},
157+
set(val: number[]) {
158+
this.expandedGroupsRaw = val;
159+
},
160+
},
161+
groups: {
162+
get() {
163+
return this.groupData;
164+
},
165+
set(v: Map<number, GroupMapType>) {
166+
for (const [k, val] of v) {
167+
this.groupData.set(k, val);
168+
}
169+
},
170+
},
171+
computedRepos() {
172+
return this.repos;
173+
},
174+
root() {
175+
return [...(this.groups.get(0)?.subgroups ?? []), ...this.repos];
176+
},
177+
loadedMap: {
178+
get() {
179+
return this.loadedRef;
180+
},
181+
set(v: Ref<Map<number, boolean>>) {
182+
this.loadedRef = v;
183+
},
184+
},
110185
},
111186
112187
mounted() {
@@ -136,6 +211,9 @@ export default defineComponent({
136211
changeReposFilter(filter: string) {
137212
this.reposFilter = filter;
138213
this.repos = [];
214+
this.groups = new Map();
215+
this.loadedMap = new Map();
216+
this.expandedGroupsRaw = [];
139217
this.page = 1;
140218
this.counts[`${filter}:${this.archivedFilter}:${this.privateFilter}`] = 0;
141219
this.searchRepos();
@@ -212,6 +290,8 @@ export default defineComponent({
212290
}
213291
this.page = 1;
214292
this.repos = [];
293+
this.groups = new Map();
294+
this.loadedMap = new Map();
215295
this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`] = 0;
216296
this.searchRepos();
217297
},
@@ -227,6 +307,8 @@ export default defineComponent({
227307
this.page = 1;
228308
}
229309
this.repos = [];
310+
this.groups = new Map();
311+
this.loadedMap = new Map();
230312
this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`] = 0;
231313
await this.searchRepos();
232314
},
@@ -235,7 +317,7 @@ export default defineComponent({
235317
this.isLoading = true;
236318
237319
const searchedMode = this.repoTypes[this.reposFilter].searchMode;
238-
const searchedURL = this.searchURL;
320+
const searchedURL = `${this.searchURL}&group_id=-1`;
239321
const searchedQuery = this.searchQuery;
240322
241323
let response, json;
@@ -257,22 +339,40 @@ export default defineComponent({
257339
response = await GET(searchedURL);
258340
json = await response.json();
259341
} catch {
260-
if (searchedURL===this.searchURL) {
342+
if (searchedURL.startsWith(this.searchURL)) {
261343
this.isLoading = false;
262344
}
263345
return;
264346
}
265347
266-
if (searchedURL===this.searchURL) {
267-
this.repos = json.data.map((webSearchRepo: any) => {
348+
if (searchedURL.startsWith(this.searchURL)) {
349+
this.repos = json.data.repos.map((webSearchRepo: any) => {
268350
return {
269351
...webSearchRepo.repository,
270352
latest_commit_status_state: webSearchRepo.latest_commit_status?.State, // if latest_commit_status is null, it means there is no commit status
271353
latest_commit_status_state_link: webSearchRepo.latest_commit_status?.TargetURL,
272354
locale_latest_commit_status_state: webSearchRepo.locale_latest_commit_status,
273355
};
274356
});
275-
const count = Number(response.headers.get('X-Total-Count'));
357+
this.groups.set(0, {
358+
repos: this.repos.filter((a: any) => !a.group_id),
359+
subgroups: json.data.subgroups.map((g: any) => {
360+
return g.group.id;
361+
}),
362+
data: {},
363+
});
364+
for (const g of json.data.subgroups) {
365+
this.groups.set(g.group.id, {
366+
subgroups: g.subgroups.map((h: any) => h.group.id),
367+
repos: g.repos,
368+
...g.group,
369+
latest_commit_status_state: g.latest_commit_status?.State, // if latest_commit_status is null, it means there is no commit status
370+
latest_commit_status_state_link: g.latest_commit_status?.TargetURL,
371+
locale_latest_commit_status_state: g.locale_latest_commit_status,
372+
id: g.group.id,
373+
});
374+
}
375+
const count = this.repos.length;
276376
if (searchedQuery === '' && searchedMode === '' && this.archivedFilter === 'both') {
277377
this.reposTotalCount = count;
278378
}
@@ -372,7 +472,7 @@ export default defineComponent({
372472
<div v-else class="ui attached segment repos-search">
373473
<div class="ui small fluid action left icon input">
374474
<input type="search" spellcheck="false" maxlength="255" @input="changeReposFilter(reposFilter)" v-model="searchQuery" ref="search" @keydown="reposFilterKeyControl" :placeholder="textSearchRepos">
375-
<i class="icon loading-icon-3px" :class="{'is-loading': isLoading}"><svg-icon name="octicon-search" :size="16"/></i>
475+
<i class="icon loading-icon-3px" :class="{'is-loading': isLoading}"><svg-icon name="octicon-search" :size="16"/></i>
376476
<div class="ui dropdown icon button" :title="textFilter">
377477
<svg-icon name="octicon-filter" :size="16"/>
378478
<div class="menu">
@@ -401,69 +501,55 @@ export default defineComponent({
401501
</div>
402502
<overflow-menu class="ui secondary pointing tabular borderless menu repos-filter">
403503
<div class="overflow-menu-items tw-justify-center">
404-
<a class="item" tabindex="0" :class="{active: reposFilter === 'all'}" @click="changeReposFilter('all')">
504+
<a class="item" tabindex="0" :class="{active: reposFilter === 'all'}" @click="changeReposFilter('all')">
405505
{{ textAll }}
406506
<div v-show="reposFilter === 'all'" class="ui circular mini grey label">{{ repoTypeCount }}</div>
407507
</a>
408-
<a class="item" tabindex="0" :class="{active: reposFilter === 'sources'}" @click="changeReposFilter('sources')">
508+
<a class="item" tabindex="0" :class="{active: reposFilter === 'sources'}" @click="changeReposFilter('sources')">
409509
{{ textSources }}
410510
<div v-show="reposFilter === 'sources'" class="ui circular mini grey label">{{ repoTypeCount }}</div>
411511
</a>
412-
<a class="item" tabindex="0" :class="{active: reposFilter === 'forks'}" @click="changeReposFilter('forks')">
512+
<a class="item" tabindex="0" :class="{active: reposFilter === 'forks'}" @click="changeReposFilter('forks')">
413513
{{ textForks }}
414514
<div v-show="reposFilter === 'forks'" class="ui circular mini grey label">{{ repoTypeCount }}</div>
415515
</a>
416-
<a class="item" tabindex="0" :class="{active: reposFilter === 'mirrors'}" @click="changeReposFilter('mirrors')" v-if="isMirrorsEnabled">
516+
<a class="item" tabindex="0" :class="{active: reposFilter === 'mirrors'}" @click="changeReposFilter('mirrors')" v-if="isMirrorsEnabled">
417517
{{ textMirrors }}
418518
<div v-show="reposFilter === 'mirrors'" class="ui circular mini grey label">{{ repoTypeCount }}</div>
419519
</a>
420-
<a class="item" tabindex="0" :class="{active: reposFilter === 'collaborative'}" @click="changeReposFilter('collaborative')">
520+
<a class="item" tabindex="0" :class="{active: reposFilter === 'collaborative'}" @click="changeReposFilter('collaborative')">
421521
{{ textCollaborative }}
422522
<div v-show="reposFilter === 'collaborative'" class="ui circular mini grey label">{{ repoTypeCount }}</div>
423523
</a>
424524
</div>
425525
</overflow-menu>
426526
</div>
427527
<div v-if="repos.length" class="ui attached table segment tw-rounded-b">
428-
<ul class="repo-owner-name-list">
429-
<li class="tw-flex tw-items-center tw-py-2" v-for="(repo, index) in repos" :class="{'active': index === activeIndex}" :key="repo.id">
430-
<a class="repo-list-link muted" :href="repo.link">
431-
<svg-icon :name="repoIcon(repo)" :size="16" class="repo-list-icon"/>
432-
<div class="text truncate">{{ repo.full_name }}</div>
433-
<div v-if="repo.archived">
434-
<svg-icon name="octicon-archive" :size="16"/>
435-
</div>
436-
</a>
437-
<a class="tw-flex tw-items-center" v-if="repo.latest_commit_status_state" :href="repo.latest_commit_status_state_link || null" :data-tooltip-content="repo.locale_latest_commit_status_state">
438-
<!-- the commit status icon logic is taken from templates/repo/commit_status.tmpl -->
439-
<svg-icon :name="statusIcon(repo.latest_commit_status_state)" :class="'tw-ml-2 commit-status icon text ' + statusColor(repo.latest_commit_status_state)" :size="16"/>
440-
</a>
441-
</li>
442-
</ul>
528+
<dashboard-repo-group :items="root" :depth="1" :cur-group="0" @load-changed="(nv: boolean) => (isLoading = nv)"/>
443529
<div v-if="showMoreReposLink" class="tw-text-center">
444530
<div class="divider tw-my-0"/>
445531
<div class="ui borderless pagination menu narrow tw-my-2">
446532
<a
447-
class="item navigation tw-py-1" :class="{'disabled': page === 1}"
533+
class="item navigation tw-py-1" :class="{'disabled': page === 1}"
448534
@click="changePage(1)" :title="textFirstPage"
449535
>
450536
<svg-icon name="gitea-double-chevron-left" :size="16" class="tw-mr-1"/>
451537
</a>
452538
<a
453-
class="item navigation tw-py-1" :class="{'disabled': page === 1}"
539+
class="item navigation tw-py-1" :class="{'disabled': page === 1}"
454540
@click="changePage(page - 1)" :title="textPreviousPage"
455541
>
456542
<svg-icon name="octicon-chevron-left" :size="16" class="tw-mr-1"/>
457543
</a>
458544
<a class="active item tw-py-1">{{ page }}</a>
459545
<a
460-
class="item navigation" :class="{'disabled': page === finalPage}"
546+
class="item navigation" :class="{'disabled': page === finalPage}"
461547
@click="changePage(page + 1)" :title="textNextPage"
462548
>
463549
<svg-icon name="octicon-chevron-right" :size="16" class="tw-ml-1"/>
464550
</a>
465551
<a
466-
class="item navigation tw-py-1" :class="{'disabled': page === finalPage}"
552+
class="item navigation tw-py-1" :class="{'disabled': page === finalPage}"
467553
@click="changePage(finalPage)" :title="textLastPage"
468554
>
469555
<svg-icon name="gitea-double-chevron-right" :size="16" class="tw-ml-1"/>
@@ -496,7 +582,7 @@ export default defineComponent({
496582
<div class="text truncate">{{ org.full_name ? `${org.full_name} (${org.name})` : org.name }}</div>
497583
<div><!-- div to prevent underline of label on hover -->
498584
<span class="ui tiny basic label" v-if="org.org_visibility !== 'public'">
499-
{{ org.org_visibility === 'limited' ? textOrgVisibilityLimited: textOrgVisibilityPrivate }}
585+
{{ org.org_visibility === 'limited' ? textOrgVisibilityLimited: textOrgVisibilityPrivate }}
500586
</span>
501587
</div>
502588
</a>

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /