{{item.commit.substring(0,7)}}
@@ -59,90 +59,49 @@
return {
expanded: [],
headers: [
- { text: '', value:'tag', sortable: false },
- { text: 'Commit', value:'commit', sortable: false },
- { text: 'Message', value:'messageShort', sortable: false },
+ { text: '', value: 'tag', sortable: false },
+ { text: 'Commit', value: 'commit', sortable: false },
+ { text: 'Message', value: 'messageShort', sortable: false },
{ text: '', value: 'data-table-expand' },
- { text: 'Author', value:'author', sortable: false },
- { text: 'Time', value:'when', sortable: false },
+ { text: 'Author', value: 'author', sortable: false },
+ { text: 'Time', value: 'when', sortable: false },
],
- items: [],
- origin: null,
- local: null,
- message: null,
- status: [],
resetDialog: false,
}
},
computed: {
+ ...Vuex.mapState('signalr', ['gitLog', 'gitLogMessage', 'gitStatus']),
updatable() {
- return this.origin
- && this.origin != this.local
- && this.items.findIndex(item => item.commit == this.origin) < this.items.findIndex(item => item.commit == this.local)
+ return this.gitLog
+ && this.gitLog.origin != this.gitLog.local
+ && this.gitLog.logs.findIndex(item => item.commit == this.origin) < this.gitLog.logs.findIndex(item => item.commit == this.local)
},
modified() {
- return this.status.length > 0;
+ return this.gitStatus.length > 0;
}
},
methods: {
- init() {
- this.$signalr.on('GitLog', (name, logs, origin, local) => {
- if (this.$route.params.id == name) {
- this.items.splice(0, this.items.length, ...logs);
- this.origin = origin;
- this.local = local;
- this.message = !origin ? 'This repository does not have remote origin/master branch.' : null;
- }
- })
- this.$signalr.on('GitLogNotFound', name => {
- if (this.$route.params.id == name) {
- this.items.splice(0);
- this.status.splice(0);
- this.origin = null;
- this.local = null;
- this.message = 'This repository have not initialized git.'
- }
- })
- this.$signalr.on('GitFetchProgress', (name, progress) => {
- if (this.$route.params.id == name) {
- this.message = progress
- }
- })
- this.$signalr.on('GitStatus', (name, status) => {
- if (this.$route.params.id == name) {
- this.status.splice(0, this.status.length, ...status);
- }
- })
- },
+ ...Vuex.mapActions('signalr', ['invokeGitLog', 'invokeGitForcePull', 'invokeGitReset']),
+ ...Vuex.mapActions('ipc', ['openRepositoryDir']),
getLog(repositoryName) {
- this.$signalr.invoke('GitLog', repositoryName);
+ this.invokeGitLog({ repositoryName });
},
handleOpen() {
- ipcRenderer.send('open-repository-dir', this.$route.params.id);
+ this.openRepositoryDir({ repositoryName: this.$route.params.id });
},
handleUpdate() {
- this.$signalr.invoke('GitForcePull', this.$route.params.id);
+ this.invokeGitForcePull({ repositoryName: this.$route.params.id });
},
handleReset() {
- this.$signalr.invoke('GitReset', this.$route.params.id);
+ this.invokeGitReset({ repositoryName: this.$route.params.id });
}
},
mounted() {
- this.init();
- this.$signalr.onconnected(() => {
- this.getLog(this.$route.params.id)
- })
+ this.getLog(this.$route.params.id);
},
beforeRouteUpdate (to, from, next) {
this.getLog(to.params.id)
next();
},
- beforeRouteLeave (to, from , next) {
- this.$signalr.off('GitLog');
- this.$signalr.off('GitLogNotFound');
- this.$signalr.off('GitFetchProgress');
- this.$signalr.off('GitStatus');
- next();
- }
})
\ No newline at end of file
diff --git a/src/Aiplugs.PoshApp/Views/Shared/Repositories/Nav.cshtml b/src/Aiplugs.PoshApp/Views/Shared/Repositories/Nav.cshtml
index 4eeebec..0298ba0 100644
--- a/src/Aiplugs.PoshApp/Views/Shared/Repositories/Nav.cshtml
+++ b/src/Aiplugs.PoshApp/Views/Shared/Repositories/Nav.cshtml
@@ -52,7 +52,7 @@
{
- this.path = path;
- });
- this.$signalr.on('GitCloneFaild', name => {
- this.deleteRepository({ name });
- });
- },
- beforeRouteLeave(to, from, next) {
- const len = Math.min(to.path.length, from.path.length)
- const sameRoute = to.path.substring(0, len) === from.path.substring(0, len);
- if (!sameRoute) {
- ipcRenderer.removeAllListeners('select-repository-path-reply');
- this.$signalr.off('GitCloneFaild');
- }
- next();
+ mounted() {
+ this.loadRepositories();
}
})
\ No newline at end of file
diff --git a/src/Aiplugs.PoshApp/Views/Shared/Settings/Activation.cshtml b/src/Aiplugs.PoshApp/Views/Shared/Settings/Activation.cshtml
index 5ae0682..cdcf0fd 100644
--- a/src/Aiplugs.PoshApp/Views/Shared/Settings/Activation.cshtml
+++ b/src/Aiplugs.PoshApp/Views/Shared/Settings/Activation.cshtml
@@ -101,22 +101,31 @@
},
methods: {
...Vuex.mapActions('activation', ['activate', 'refleshActivationCode']),
+ ...Vuex.mapActions('ipc', ['copyTo']),
openEx() {
ipcRenderer.send("open-activation");
},
async copyRequestCode() {
- await ipcRenderer.send("copy-to", this.requestCode);
+ await this.copyTo(this.requestCode);
alert("Copied!");
},
async handleReflesh() {
- this.loading = true;
- await this.refleshActivationCode();
- this.loading = false;
+ try {
+ this.loading = true;
+ await this.refleshActivationCode();
+ }
+ finally {
+ this.loading = false;
+ }
},
async handleActivation() {
- this.loading = true;
- await this.activate(this.activationCode);
- this.loading = false;
+ try {
+ this.loading = true;
+ await this.activate(this.activationCode);
+ }
+ finally {
+ this.loading = false;
+ }
}
}
})
diff --git a/src/Aiplugs.PoshApp/wwwroot/js/main.js b/src/Aiplugs.PoshApp/wwwroot/js/main.js
index 7600fa6..0b22b9a 100644
--- a/src/Aiplugs.PoshApp/wwwroot/js/main.js
+++ b/src/Aiplugs.PoshApp/wwwroot/js/main.js
@@ -3,11 +3,11 @@ import router from './router.js';
Vue.prototype.$signalr = new signalR.HubConnectionBuilder().withUrl("/poshapp").withAutomaticReconnect().build();
Vue.prototype.$signalr.onconnected = function (callback) {
- const f = () => {
+ const f = () => {
if (this.state === 'Connected') { callback(); }
else { setTimeout(f, 10); }
}; f();
-}
+};
const app = new Vue({
el: '#app',
diff --git a/src/Aiplugs.PoshApp/wwwroot/js/store/index.js b/src/Aiplugs.PoshApp/wwwroot/js/store/index.js
index b2a9b67..5c0eb92 100644
--- a/src/Aiplugs.PoshApp/wwwroot/js/store/index.js
+++ b/src/Aiplugs.PoshApp/wwwroot/js/store/index.js
@@ -1,8 +1,10 @@
-import list from './list.js'
-import toast from './toast.js'
-import scripts from './scripts.js'
-import repositories from './repositories.js'
-import activation from './activation.js'
+import list from './list.js';
+import toast from './toast.js';
+import scripts from './scripts.js';
+import repositories from './repositories.js';
+import activation from './activation.js';
+import signalr, { signalRPlugin } from './signalr.js';
+import ipc, { ipcPlugin } from './ipc.js';
export default new Vuex.Store({
modules: {
@@ -10,6 +12,9 @@ export default new Vuex.Store({
toast,
scripts,
repositories,
- activation
- }
+ activation,
+ signalr,
+ ipc
+ },
+ plugins: [signalRPlugin, ipcPlugin]
});
diff --git a/src/Aiplugs.PoshApp/wwwroot/js/store/ipc.js b/src/Aiplugs.PoshApp/wwwroot/js/store/ipc.js
new file mode 100644
index 0000000..1a50c90
--- /dev/null
+++ b/src/Aiplugs.PoshApp/wwwroot/js/store/ipc.js
@@ -0,0 +1,74 @@
+if (!window.ipcRenderer) {
+ window.ipcRenderer = {
+ on: function () { },
+ send: function () { },
+ removeAllListeners: function () { },
+ };
+}
+export default {
+ namespaced: true,
+ state: {
+ updateAvailable: false,
+ selectedDirectory: {},
+ selectedFile: {}
+ },
+ mutations: {
+ setUpdateAvailable(state) {
+ state.updateAvailable = true;
+ },
+ clearUpdateAvailable(state) {
+ state.updateAvailable = false;
+ },
+ setSelectedDirectory(state, { name, path }) {
+ Vue.set(state.selectedDirectory, name, path);
+ },
+ clearSelectedDirectory(state) {
+ state.selectedDirectory = {};
+ },
+ setSelectedFile(state, { name, path }) {
+ Vue.set(state.selectedFile, name, path);
+ },
+ clearSelectedFile(state) {
+ state.selectedFile = {};
+ }
+ },
+ actions: {
+ checkForUpdates() {
+ ipcRenderer.send('check-for-updates');
+ },
+ quitAndInstall() {
+ ipcRenderer.send('quit-and-install');
+ },
+ clearSelected({ commit }) {
+ commit('clearSelectedDirectory');
+ commit('clearSelectedFile');
+ },
+ selectDirectory(_, { name }) {
+ ipcRenderer.send('select-directory', name);
+ },
+ selectFile(_, { name }) {
+ ipcRenderer.send('select-file', name);
+ },
+ openActivation() {
+ ipcRenderer.send('open-activation');
+ },
+ copyTo(_, text) {
+ ipcRenderer.send('copy-to', text);
+ },
+ openRepositoryDir(_, { repositoryName }) {
+ ipcRenderer.send('open-repository-dir', repositoryName);
+ }
+ }
+};
+
+export function ipcPlugin(store) {
+ ipcRenderer.on('update-available', sender => {
+ store.commit('ipc/setUpdateAvailable');
+ });
+ ipcRenderer.on('select-directory-reply', (sender, path, name) => {
+ store.commit('ipc/setSelectedDirectory', { path, name });
+ });
+ ipcRenderer.on('select-file-reply', (sender, path, name) => {
+ store.commit('ipc/setSelectedFile', { path, name });
+ });
+}
diff --git a/src/Aiplugs.PoshApp/wwwroot/js/store/signalr.js b/src/Aiplugs.PoshApp/wwwroot/js/store/signalr.js
new file mode 100644
index 0000000..898b246
--- /dev/null
+++ b/src/Aiplugs.PoshApp/wwwroot/js/store/signalr.js
@@ -0,0 +1,307 @@
+import { parsePSDataCollection } from '/js/clixml.js';
+const signalr = new signalR.HubConnectionBuilder().withUrl("/poshapp").withAutomaticReconnect().build();
+let init = signalr.start();
+
+export default {
+ namespaced: true,
+ state: {
+ connectionId: null,
+ status: 'connecting',
+ invoking: null,
+ loadingParams: false,
+ defaultResult: null,
+ detailResult: null,
+ parameters: [],
+ logMessages: [],
+ logErrors: null,
+ progresses: {},
+ prompt: null,
+ promptForChoice: null,
+ promptForCredential: null,
+ gitClone: null,
+ gitLog: null,
+ gitLogMessage: null,
+ gitStatus: []
+ },
+ mutations: {
+ setInvoking(state, name = '$default') {
+ state.invoking = name;
+ },
+ clearInvoking(state) {
+ state.invoking = null;
+ },
+ setLoadingParams(state) {
+ state.loadingParams = true;
+ },
+ clearLoadingParams(state) {
+ state.loadingParams = false;
+ },
+ setDefaultResult(state, result) {
+ state.defaultResult = result;
+ },
+ setDetailResult(state, result) {
+ state.detailResult = result;
+ },
+ setParameters(state, parameters) {
+ state.parameters.splice(0, state.parameters.length, ...parameters);
+ },
+ writeHost(state, { color, bgColor, text }) {
+ if (state.logMessages.length > 30) {
+ state.logMessages.shift();
+ }
+ state.logMessages.push({ color, bgColor, text });
+ },
+ writeWarning(state, { message }) {
+ state.logMessages.push({
+ color: 6,
+ bgColor: 0,
+ text: message
+ });
+ },
+ writeError(state, { message }) {
+ const text = message.replace(/\r\n/g, '\n').split('\n').filter(line => !line.match(/^\s*$/)).join('\n');
+ if (state.logErrors !== null) {
+ state.logErrors += '\n\n' + text;
+ }
+ else {
+ state.logErrors = text;
+ }
+ },
+ clearError(state) {
+ state.logErrors = null;
+ },
+ writeDebug(state, { message }) {
+ state.logMessages.push({
+ color: 15,
+ bgColor: 0,
+ text: message
+ });
+ },
+ writeVerbose(state, { message }) {
+ state.logMessages.push({
+ color: 15,
+ bgColor: 0,
+ text: message
+ });
+ },
+ writeInformation(state, { }) {
+ state.logMessages.push({
+ color: 15,
+ bgColor: 0,
+ text: message
+ });
+ },
+ writeProgress(state, { progress }) {
+ Vue.set(state.progresses, progress.activityId.toString(), progress);
+ if (progress.percentComplete === 100) {
+ Vue.delete(state.progresses, progress.activityId);
+ }
+ },
+ setPrompt(state, { caption, message, descriptions }) {
+ state.prompt = { caption, message, descriptions };
+ },
+ clearPrompt(state) {
+ state.prompt = null;
+ },
+ setPromptForChoice(state, { caption, message, choices, defaultChoice }) {
+ state.promptForChoice = { caption, message, choices, defaultChoice };
+ },
+ clearPromptForChoice(state) {
+ state.promptForChoice = null;
+ },
+ setPromptForCredential(state, { caption, message, userName, targetName, allowedCredentialTypes, forGit }) {
+ state.promptForCredential = { caption, message, userName, targetName, allowedCredentialTypes, forGit };
+ },
+ clearPromptForCredential(state) {
+ state.promptForCredential = null;
+ },
+ setGitProgress(state, { name, progress }) {
+ state.gitClone = { name, progress };
+ },
+ setGitClone(state, { name }) {
+ state.gitClone = null;
+ },
+ setGitCloneFaild(state, { name }) {
+ state.gitClone = null;
+ },
+ setGitLog(state, { name, logs, origin, local }) {
+ state.gitLog = { name, logs, origin, local };
+ state.gitLogMessage = !origin ? 'This repository does not have remote origin/master branch.' : null;
+ },
+ clearGitLog(state) {
+ state.gitLog = null;
+ state.gitLogMessage = null;
+ },
+ setGitLogNotFound(state, { name }) {
+ state.gitLogMessage = 'This repository have not initialized git.';
+ },
+ setGitFetchProgress(state, { name, progress }) {
+ state.gitLogMessage = progress;
+ },
+ setGitStatus(state, { name, status }) {
+ state.gitStatus.splice(0, state.gitStatus.length, ...status);
+ },
+ setStatus(state, { status, connectionId }) {
+ state.status = status;
+ state.connectionId = connectionId;
+ }
+ },
+ actions: {
+ clearResult({ commit }) {
+ commit('setDefaultResult', null);
+ commit('setDetailResult', null);
+ },
+ async invokeDefault({ commit }, { scriptId, input }) {
+ commit('setInvoking');
+ await signalr.invoke('Invoke', scriptId, input);
+ },
+ async invokeDetail({ commit },{ scriptId, input }) {
+ commit('setInvoking');
+ await signalr.invoke('InvokeDetail', scriptId, input);
+ },
+ async invokeAction({ commit }, { scriptId, input }) {
+ commit('setInvoking', scriptId);
+ await signalr.invoke('InvokeAction', scriptId, input);
+ },
+ async invokeGetParameters({ commit }, { scriptId }) {
+ commit('setParameters', []);
+ commit('setLoadingParams', []);
+ await init;
+ await signalr.invoke('GetParameters', scriptId);
+ },
+ async invokePrompt({ commit }, { input }) {
+ commit('clearPrompt');
+ await signalr.invoke('Prompt', input);
+ },
+ async invokePromptForChoice({ commit }, { index }) {
+ commit('clearPromptForChoice');
+ await signalr.invoke('PromptForChoice', index);
+ },
+ async invokePromptForCredential({ commit }, { username, password }) {
+ commit('clearPromptForCredential');
+ await signalr.invoke('PromptForCredential', username, password);
+ },
+ async invokePromptForGitCredential({ commit }, { username, password }) {
+ commit('clearPromptForCredential');
+ await signalr.invoke('PromptForGitCredential', username, password);
+ },
+ async invokeGitLog({ commit }, { repositoryName }) {
+ commit('clearGitLog');
+ await init;
+ await signalr.invoke('GitLog', repositoryName);
+ },
+ async invokeGitForcePull(_, { repositoryName }) {
+ await signalr.invoke('GitForcePull', repositoryName);
+ },
+ async invokeGitReset(_, { repositoryName }) {
+ await signalr.invoke('GitReset', repositoryName);
+ },
+ async reconnect({ commit }) {
+ if (signalr.state === 'Disconnected') {
+ init = signalr.start();
+ }
+ else if (signalr.state === 'Connected') {
+ commit('signalr/setStatus', { status: 'connected', connectionId: signalr.connectionId });
+ }
+ }
+ }
+};
+
+export function signalRPlugin(store) {
+ signalr.on('UnitResult', () => {
+ store.commit('signalr/clearInvoking');
+ });
+ signalr.on('DefaultResult', json => {
+ store.commit('signalr/clearInvoking');
+ store.commit('signalr/setDefaultResult', parsePSDataCollection(JSON.parse(json)));
+ });
+ signalr.on('DetailResult', json => {
+ store.commit('signalr/clearInvoking');
+ store.commit('signalr/setDetailResult', parsePSDataCollection(JSON.parse(json)));
+ });
+ signalr.on('ActionResult', (id, json) => {
+ store.commit('signalr/clearInvoking');
+ store.dispatch('toast/toast', {
+ text: `${id} is succeeded`,
+ color: "info",
+ top: true,
+ right: true
+ });
+ });
+ signalr.on('GetParameters', parameters => {
+ store.commit('signalr/clearLoadingParams');
+ store.commit('signalr/setParameters', parameters);
+ });
+ signalr.on('WriteWithColor', (color, bgColor, text) => {
+ store.commit('signalr/writeHost', { color, bgColor, text });
+ });
+ signalr.on('WriteWarningLine', message => {
+ store.commit('signalr/writeWarning', { message });
+ });
+ signalr.on('WriteErrorLine', message => {
+ store.commit('signalr/writeError', { message });
+ });
+ signalr.on('WriteDebugLine', message => {
+ store.commit('signalr/writeDebug', { message });
+ });
+ signalr.on('WriteVerboseLine', message => {
+ store.commit('signalr/writeVerbose', { message });
+ });
+ signalr.on('WriteProgress', (sourceId, progress) => {
+ store.commit('signalr/writeProgress', { progress });
+ });
+ signalr.on('ParseError', message => {
+ store.commit('signalr/writeError', { message });
+ });
+ signalr.on('Prompt', (caption, message, descriptions) => {
+ store.commit('signalr/setPrompt', { caption, message, descriptions });
+ });
+ signalr.on('PromptForChoice', (caption, message, choices, defaultChoice) => {
+ store.commit('signalr/setPromptForChoice', { caption, message, choices, defaultChoice });
+ });
+ signalr.on('PromptForCredential', (caption, message, userName, targetName) => {
+ store.commit('signalr/setPromptForCredential', { caption, message, userName, targetName, allowedCredentialTypes: null, forGit: false });
+ });
+ signalr.on('PromptForCredentialWithType', (caption, message, userName, targetName, allowedCredentialTypes) => {
+ store.commit('signalr/setPromptForCredential', { caption, message, userName, targetName, allowedCredentialTypes, forGit: false });
+ });
+ signalr.on('PromptForGitCredential', (url, usernameFromUrl) => {
+ store.commit('signalr/setPromptForCredential', { caption: url, message: url, userName: usernameFromUrl, targetName: null, allowedCredentialTypes: null, forGit: true });
+ });
+ signalr.on('GitProgress', (name, progress) => {
+ store.commit('signalr/setGitProgress', { name, progress });
+ });
+ signalr.on('GitClone', name => {
+ store.commit('signalr/setGitClone', { name });
+ });
+ signalr.on('GitCloneFaild', name => {
+ store.commit('signalr/setGitCloneFaild', { name });
+ });
+ signalr.on('GitLog', (name, logs, origin, local) => {
+ store.commit('signalr/setGitLog', { name, logs, origin, local });
+ });
+ signalr.on('GitLogNotFound', name => {
+ store.commit('signalr/setGitLogNotFound', { name });
+ });
+ signalr.on('GitFetchProgress', (name, progress) => {
+ store.commit('signalr/setGitFetchProgress', { name, progress });
+ });
+ signalr.on('GitStatus', (name, status) => {
+ store.commit('signalr/setGitStatus', { name, status });
+ });
+
+ signalr.onclose(err => {
+ store.commit('signalr/setStatus', { status: 'close' });
+ });
+ signalr.onreconnecting(err => {
+ store.commit('signalr/setStatus', { status: 'reconnecting' });
+ });
+ signalr.onreconnected(connectedId => {
+ store.commit('signalr/setStatus', { status: 'connected', connectionId: signalr.connectionId });
+ });
+ init.then(() => {
+ store.commit('signalr/setStatus', { status: 'connected', connectionId: signalr.connectionId });
+ }).catch(() => {
+ store.commit('signalr/setStatus', { status: 'faild' });
+ });
+}
\ No newline at end of file