Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Take a stab at porting existing components to Vue3 #20044

Merged
merged 10 commits into from
Oct 1, 2022
804 changes: 336 additions & 468 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"dependencies": {
"@claviska/jquery-minicolors": "2.3.6",
"@primer/octicons": "17.2.0",
"@vue/compiler-sfc": "3.2.37",
"add-asset-webpack-plugin": "2.0.1",
"css-loader": "6.7.1",
"dropzone": "6.0.0-beta.2",
Expand All @@ -31,11 +32,10 @@
"swagger-ui-dist": "4.11.1",
"tributejs": "5.1.3",
"uint8-to-base64": "0.2.0",
"vue": "2.6.14",
"vue-bar-graph": "1.3.1",
"vue-calendar-heatmap": "0.8.4",
"vue-loader": "15.9.8",
"vue-template-compiler": "2.6.14",
"vue": "3.2.37",
"vue-bar-graph": "2.0.0",
"vue-loader": "17.0.0",
"vue3-calendar-heatmap": "2.0.0",
"webpack": "5.72.1",
"webpack-cli": "4.9.2",
"workbox-routing": "6.5.3",
Expand Down
2 changes: 1 addition & 1 deletion web_src/js/components/ActivityHeatmap.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
</div>
</template>
<script>
wxiaoguang marked this conversation as resolved.
Show resolved Hide resolved
import {CalendarHeatmap} from 'vue-calendar-heatmap';
import {CalendarHeatmap} from 'vue3-calendar-heatmap';
6543 marked this conversation as resolved.
Show resolved Hide resolved

export default {
name: 'ActivityHeatmap',
Expand Down
29 changes: 14 additions & 15 deletions web_src/js/components/DashboardRepoList.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import Vue from 'vue';
import {createApp, nextTick} from 'vue';
import $ from 'jquery';
import {initVueSvg, vueDelimiters} from './VueComponentLoader.js';

const {appSubUrl, assetUrlPrefix, pageData} = window.config;

function initVueComponents() {
Vue.component('repo-search', {
function initVueComponents(app) {
app.component('repo-search', {
6543 marked this conversation as resolved.
Show resolved Hide resolved
delimiters: vueDelimiters,
props: {
searchLimit: {
Expand Down Expand Up @@ -141,7 +141,7 @@ function initVueComponents() {
$(this.$el).find('.tooltip').popup();
$(this.$el).find('.dropdown').dropdown();
this.setCheckboxes();
Vue.nextTick(() => {
nextTick(() => {
this.$refs.search.focus();
});
},
Expand Down Expand Up @@ -189,7 +189,7 @@ function initVueComponents() {
this.reposFilter = filter;
this.repos = [];
this.page = 1;
Vue.set(this.counts, `${filter}:${this.archivedFilter}:${this.privateFilter}`, 0);
this.counts[`${filter}:${this.archivedFilter}:${this.privateFilter}`] = 0;
this.searchRepos();
},

Expand Down Expand Up @@ -258,7 +258,7 @@ function initVueComponents() {
this.page = 1;
this.repos = [];
this.setCheckboxes();
Vue.set(this.counts, `${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`, 0);
this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`] = 0;
this.searchRepos();
},

Expand All @@ -280,7 +280,7 @@ function initVueComponents() {
this.page = 1;
this.repos = [];
this.setCheckboxes();
Vue.set(this.counts, `${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`, 0);
this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`] = 0;
this.searchRepos();
},

Expand All @@ -294,7 +294,7 @@ function initVueComponents() {
this.page = 1;
}
this.repos = [];
Vue.set(this.counts, `${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`, 0);
this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`] = 0;
this.searchRepos();
},

Expand Down Expand Up @@ -328,7 +328,7 @@ function initVueComponents() {
if (searchedQuery === '' && searchedMode === '' && this.archivedFilter === 'both') {
this.reposTotalCount = count;
}
Vue.set(this.counts, `${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`, count);
this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`] = count;
this.finalPage = Math.ceil(count / this.searchLimit);
this.updateHistory();
this.isLoading = false;
Expand All @@ -353,23 +353,22 @@ function initVueComponents() {
});
}


export function initDashboardRepoList() {
const el = document.getElementById('dashboard-repo-list');
const dashboardRepoListData = pageData.dashboardRepoList || null;
if (!el || !dashboardRepoListData) return;

initVueSvg();
initVueComponents();
new Vue({
el,
const app = createApp({
delimiters: vueDelimiters,
data: () => {
data() {
return {
searchLimit: dashboardRepoListData.searchLimit || 0,
subUrl: appSubUrl,
uid: dashboardRepoListData.uid || 0,
};
},
});
initVueSvg(app);
initVueComponents(app);
app.mount(el);
}
13 changes: 6 additions & 7 deletions web_src/js/components/RepoBranchTagDropdown.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Vue from 'vue';
import {createApp, nextTick} from 'vue';
import $ from 'jquery';
import {vueDelimiters} from './VueComponentLoader.js';

Expand Down Expand Up @@ -37,8 +37,7 @@ export function initRepoBranchTagDropdown(selector) {
});
});
$data.remove();
new Vue({
el: this,
createApp({
6543 marked this conversation as resolved.
Show resolved Hide resolved
delimiters: vueDelimiters,
data,
computed: {
Expand Down Expand Up @@ -99,7 +98,7 @@ export function initRepoBranchTagDropdown(selector) {
document.body.addEventListener('click', (event) => {
if (this.$el.contains(event.target)) return;
if (this.menuVisible) {
Vue.set(this, 'menuVisible', false);
this.menuVisible = false;
}
});
},
Expand Down Expand Up @@ -135,15 +134,15 @@ export function initRepoBranchTagDropdown(selector) {
if (this.submitForm) {
$(`#${this.branchForm}`).trigger('submit');
}
Vue.set(this, 'menuVisible', false);
this.menuVisible = false;
}
},
createNewBranch() {
if (!this.showCreateNewBranch) return;
$(this.$refs.newBranchForm).trigger('submit');
},
focusSearchField() {
Vue.nextTick(() => {
nextTick(() => {
this.$refs.searchField.focus();
});
},
Expand Down Expand Up @@ -212,6 +211,6 @@ export function initRepoBranchTagDropdown(selector) {
}
}
}
});
}).mount(this);
});
}
17 changes: 9 additions & 8 deletions web_src/js/components/VueComponentLoader.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Vue from 'vue';
import {createApp} from 'vue';
import {svgs} from '../svg.js';

export const vueDelimiters = ['${', '}'];
Expand All @@ -8,13 +8,15 @@ export function initVueEnv() {
if (vueEnvInited) return;
vueEnvInited = true;

/* As far as I could tell, this is no longer possible.
* But there seem not to be a guide what to do instead.
const isProd = window.config.runModeIsProd;
Vue.config.productionTip = false;
Vue.config.devtools = !isProd;
*/
}

let vueSvgInited = false;
export function initVueSvg() {
export function initVueSvg(app) {
6543 marked this conversation as resolved.
Show resolved Hide resolved
if (vueSvgInited) return;
vueSvgInited = true;

Expand All @@ -24,7 +26,7 @@ export function initVueSvg() {
.replace(/height="[0-9]+"/, 'v-bind:height="size"')
.replace(/width="[0-9]+"/, 'v-bind:width="size"');

Vue.component(name, {
app.component(name, {
props: {
size: {
type: String,
Expand All @@ -42,8 +44,7 @@ export function initVueApp(el, opts = {}) {
}
if (!el) return null;

return new Vue(Object.assign({
el,
delimiters: vueDelimiters,
}, opts));
return createApp(
Object.assign({delimiters: vueDelimiters}, opts)
).mount(el);
}
8 changes: 3 additions & 5 deletions web_src/js/features/contextpopup.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import $ from 'jquery';
import Vue from 'vue';
import {createApp} from 'vue';
import ContextPopup from '../components/ContextPopup.vue';
import {parseIssueHref} from '../utils.js';

Expand All @@ -20,14 +20,12 @@ export default function initContextPopups() {
el.innerHTML = '<div></div>';
this.parentNode.insertBefore(el, this.nextSibling);

const View = Vue.extend({
const view = createApp({
6543 marked this conversation as resolved.
Show resolved Hide resolved
render: (createElement) => createElement(ContextPopup),
});

const view = new View();

try {
view.$mount(el.firstChild);
view.mount(el.firstChild);
} catch (err) {
console.error(err);
el.textContent = 'ContextPopup failed to load';
Expand Down
6 changes: 3 additions & 3 deletions web_src/js/features/heatmap.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Vue from 'vue';
import {createApp} from 'vue';
import ActivityHeatmap from '../components/ActivityHeatmap.vue';

export default function initHeatmap() {
Expand All @@ -17,11 +17,11 @@ export default function initHeatmap() {
return {date: new Date(v), count: heatmap[v]};
});

const View = Vue.extend({
const View = createApp({
render: (createElement) => createElement(ActivityHeatmap, {props: {values}}),
});

new View().$mount(el);
View.mount(el);
} catch (err) {
console.error('Heatmap failed to load', err);
el.textContent = 'Heatmap failed to load';
Expand Down
6 changes: 3 additions & 3 deletions web_src/js/features/repo-issue-pr-form.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import Vue from 'vue';
import {createApp} from 'vue';
import PullRequestMergeForm from '../components/PullRequestMergeForm.vue';

export default function initPullRequestMergeForm() {
const el = document.getElementById('pull-request-merge-form');
if (!el) return;

const View = Vue.extend({
const View = createApp({
wxiaoguang marked this conversation as resolved.
Show resolved Hide resolved
render: (createElement) => createElement(PullRequestMergeForm),
});
new View().$mount(el);
View.mount(el);
}
7 changes: 3 additions & 4 deletions web_src/js/svg.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ import octiconRepoTemplate from '../../public/img/svg/octicon-repo-template.svg'
import octiconTriangleDown from '../../public/img/svg/octicon-triangle-down.svg';
import octiconFile from '../../public/img/svg/octicon-file.svg';

import Vue from 'vue';

export const svgs = {
'octicon-chevron-down': octiconChevronDown,
'octicon-chevron-right': octiconChevronRight,
Expand Down Expand Up @@ -58,7 +56,8 @@ export function svg(name, size = 16, className = '') {
return serializer.serializeToString(svgNode);
}

export const SvgIcon = Vue.component('SvgIcon', {
export const SvgIcon = {
name: 'SvgIcon',
6543 marked this conversation as resolved.
Show resolved Hide resolved
props: {
name: {type: String, required: true},
size: {type: Number, default: 16},
Expand All @@ -72,4 +71,4 @@ export const SvgIcon = Vue.component('SvgIcon', {
},

template: `<span v-html="svg" />`
});
};
6 changes: 1 addition & 5 deletions webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@ import AddAssetPlugin from 'add-asset-webpack-plugin';
import LicenseCheckerWebpackPlugin from 'license-checker-webpack-plugin';
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
import MonacoWebpackPlugin from 'monaco-editor-webpack-plugin';
import VueLoader from 'vue-loader';
import {VueLoaderPlugin} from 'vue-loader';
import EsBuildLoader from 'esbuild-loader';
import {parse, dirname} from 'path';
import webpack from 'webpack';
import {fileURLToPath} from 'url';

const {VueLoaderPlugin} = VueLoader;
const {ESBuildMinifyPlugin} = EsBuildLoader;
const {SourceMapDevToolPlugin} = webpack;
const glob = (pattern) => fastGlob.sync(pattern, {
Expand Down Expand Up @@ -228,9 +227,6 @@ export default {
},
resolve: {
symlinks: false,
alias: {
vue$: 'vue/dist/vue.esm.js', // needed because vue's default export is the runtime only
},
},
watchOptions: {
ignored: [
Expand Down