forked from owncloud/web
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add external app for appProvider iFrames
- Loading branch information
1 parent
57daa52
commit 7980e48
Showing
18 changed files
with
534 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
Enhancement: Add wrapper app for external apps | ||
|
||
We have added a `external` app that can render apps | ||
coming from the oCIS AppProvider via iFrame. | ||
|
||
https://github.com/owncloud/web/pull/5805 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
[main] | ||
host = https://www.transifex.com | ||
|
||
[owncloud-web.external] | ||
file_filter = locale/<lang>/LC_MESSAGES/app.po | ||
minimum_perc = 0 | ||
source_file = template.pot | ||
source_lang = en | ||
type = PO | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{"de":{"Close":"Schließen","Download":"Herunterladen"}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"name": "external", | ||
"version": "0.0.0", | ||
"description": "ownCloud web integration of the reva app provider", | ||
"license": "AGPL-3.0", | ||
"devDependencies": { | ||
"vue": "^2.6.10", | ||
"vuex": "3.6.2" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
<template> | ||
<main | ||
class="uk-height-viewport" | ||
:class="{ | ||
'uk-flex uk-flex-center uk-flex-middle': loading || loadingError | ||
}" | ||
> | ||
<h1 class="oc-invisible-sr" v-text="pageTitle" /> | ||
<loading-screen v-if="loading" /> | ||
<error-screen v-else-if="loadingError" /> | ||
<iframe | ||
v-if="appUrl && method === 'GET'" | ||
:src="appUrl" | ||
class="uk-width-1-1 uk-height-viewport" | ||
:title="iFrameTitle" | ||
/> | ||
<div v-if="appUrl && method === 'POST' && formParameters"> | ||
<form :action="appUrl" target="app-iframe" method="post"> | ||
<input ref="subm" type="submit" :value="formParameters" class="oc-hidden" /> | ||
<div v-for="(item, key, index) in formParameters" :key="index"> | ||
<input :name="key" :value="item" type="hidden" /> | ||
</div> | ||
</form> | ||
<iframe name="app-iframe" class="uk-width-1-1 uk-height-viewport" :title="iFrameTitle" /> | ||
</div> | ||
</main> | ||
</template> | ||
|
||
<script> | ||
import { mapGetters } from 'vuex' | ||
import ErrorScreen from './components/ErrorScreen.vue' | ||
import LoadingScreen from './components/LoadingScreen.vue' | ||
export default { | ||
name: 'ExternalApp', | ||
components: { | ||
ErrorScreen, | ||
LoadingScreen | ||
}, | ||
data: () => ({ | ||
loading: false, | ||
loadingError: false, | ||
appUrl: '', | ||
method: '', | ||
formParameters: {} | ||
}), | ||
computed: { | ||
...mapGetters(['getToken', 'capabilities', 'configuration']), | ||
pageTitle() { | ||
const translated = this.$gettext('"%{appName}" app page') | ||
return this.$gettextInterpolate(translated, { | ||
appName: this.appName | ||
}) | ||
}, | ||
iFrameTitle() { | ||
const translated = this.$gettext('"%{appName}" app content area') | ||
return this.$gettextInterpolate(translated, { | ||
appName: this.appName | ||
}) | ||
}, | ||
appName() { | ||
return this.$route.params.app | ||
}, | ||
fileId() { | ||
return this.$route.params.file_id + '==' | ||
} | ||
}, | ||
async created() { | ||
this.loading = true | ||
// TODO: Enable externalApp usage on public routes below | ||
// initialize headers() | ||
// if (this.isPublicRoute) { | ||
// // send auth header here if public route | ||
// // if password exists send it via basicauth public:password | ||
// // headers.append('public-token', 'uUCPJghnVUspjxe') | ||
// // const password = this.publicLinkPassword | ||
// // if (password) { | ||
// // headers.append( Authorization: 'Basic ' + Buffer.from('public:' + password).toString('base64') } | ||
// // } | ||
// } else { | ||
// - check for token | ||
// - abort if falsy | ||
// - build headers as below | ||
// } | ||
if (!this.getToken) { | ||
this.loading = false | ||
this.loadingError = true | ||
return | ||
} | ||
const headers = new Headers() | ||
headers.append('Authorization', 'Bearer ' + this.getToken) | ||
headers.append('X-Requested-With', 'XMLHttpRequest') | ||
const configUrl = this.configuration.server | ||
const appOpenUrl = this.capabilities.files.app_providers[0].open_url.replace('/app', 'app') | ||
const url = configUrl + appOpenUrl + '?file_id=' + this.fileId + '&app_name=' + this.appName | ||
const response = await fetch(url, { | ||
method: 'POST', | ||
headers | ||
}) | ||
if (response.status !== 200) { | ||
this.loading = false | ||
this.loadingError = true | ||
console.error('Error fetching app information', response.status, response.message) | ||
return | ||
} | ||
const data = await response.json() | ||
if (!data.app_url || !data.method) { | ||
this.loading = false | ||
this.loadingError = true | ||
console.error('Error in app server response') | ||
return | ||
} | ||
this.appUrl = data.app_url | ||
this.method = data.method | ||
if (data.form_parameters) this.formParameters = data.form_parameters | ||
if (this.method === 'POST' && this.formParameters) { | ||
this.$nextTick(() => this.$refs.subm.click()) | ||
} | ||
this.loading = false | ||
} | ||
} | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<template> | ||
<div class="uk-text-center"> | ||
<oc-icon size="xxlarge" name="warning" /> | ||
<p v-translate>Error when loading the application</p> | ||
</div> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<template> | ||
<div class="uk-text-center"> | ||
<oc-spinner size="xlarge" /> | ||
<p v-translate class="oc-invisible">Loading app</p> | ||
</div> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import translations from '../l10n/translations' | ||
|
||
import App from './App.vue' | ||
import store from './store' | ||
|
||
const appInfo = { | ||
name: 'External', | ||
id: 'external' | ||
} | ||
|
||
const routes = [ | ||
{ | ||
name: 'apps', | ||
path: '/:app/:file_id', | ||
components: { | ||
app: App | ||
} | ||
} | ||
] | ||
|
||
async function fetchAvailableMimeTypes() { | ||
const vueStore = window.Vue.$store | ||
if (!vueStore.getters.capabilities.files.app_providers[0]?.enabled) { | ||
return | ||
} | ||
const serverUrl = vueStore.getters.configuration.server | ||
const appList = vueStore.getters.capabilities.files.app_providers[0].apps_url | ||
const url = serverUrl + appList.replace('/app', 'app') | ||
await vueStore.dispatch('External/fetchMimeTypes', url) | ||
} | ||
|
||
export default { | ||
appInfo, | ||
routes, | ||
store, | ||
translations, | ||
async mounted() { | ||
await fetchAvailableMimeTypes() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
const state = { | ||
mimeTypes: {} | ||
} | ||
|
||
const actions = { | ||
async fetchMimeTypes(context, url: string): Promise<void> { | ||
const response = await fetch(url) | ||
|
||
if (!response.ok) { | ||
throw new Error('Error fetching app provider MIME types') | ||
} | ||
|
||
const mimeTypes = await response.json() | ||
|
||
context.commit('SET_MIME_TYPES', mimeTypes['mime-types']) | ||
} | ||
} | ||
|
||
const getters = { | ||
getMimeTypes: state => { | ||
return state.mimeTypes | ||
} | ||
} | ||
|
||
const mutations = { | ||
SET_MIME_TYPES(state, mimeTypes): void { | ||
state.mimeTypes = mimeTypes | ||
} | ||
} | ||
|
||
export default { | ||
namespaced: true, | ||
state, | ||
actions, | ||
mutations, | ||
getters | ||
} |
50 changes: 50 additions & 0 deletions
50
packages/web-app-external/tests/unit/__snapshots__/app.spec.js.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`The app provider extension should be able to load an iFrame via get 1`] = ` | ||
<main class="uk-height-viewport"> | ||
<h1 class="oc-invisible-sr">"exampleApp" app page</h1> | ||
<!----> <iframe src="https://example.test/d12ab86/loe009157-MzBw" title=""exampleApp" app content area" class="uk-width-1-1 uk-height-viewport"></iframe> | ||
<!----> | ||
</main> | ||
`; | ||
|
||
exports[`The app provider extension should be able to load an iFrame via post 1`] = ` | ||
<main class="uk-height-viewport"> | ||
<h1 class="oc-invisible-sr">"exampleApp" app page</h1> | ||
<!----> | ||
<!----> | ||
<div> | ||
<form action="https://example.test/d12ab86/loe009157-MzBw" target="app-iframe" method="post"><input type="submit" class="oc-hidden" value="[object Object]"> | ||
<div><input name="access_token" type="hidden" value="asdfsadfsadf"></div> | ||
<div><input name="access_token_ttl" type="hidden" value="123456"></div> | ||
</form> <iframe name="app-iframe" title=""exampleApp" app content area" class="uk-width-1-1 uk-height-viewport"></iframe> | ||
</div> | ||
</main> | ||
`; | ||
exports[`The app provider extension should fail for unauthenticated users 1`] = ` | ||
<main class="uk-height-viewport uk-flex uk-flex-center uk-flex-middle"> | ||
<h1 class="oc-invisible-sr">"exampleApp" app page</h1> | ||
<errorscreen-stub></errorscreen-stub> | ||
<!----> | ||
<!----> | ||
</main> | ||
`; | ||
exports[`The app provider extension should show a loading spinner while loading 1`] = ` | ||
<main class="uk-height-viewport uk-flex uk-flex-center uk-flex-middle"> | ||
<h1 class="oc-invisible-sr">"exampleApp" app page</h1> | ||
<loadingscreen-stub></loadingscreen-stub> | ||
<!----> | ||
<!----> | ||
</main> | ||
`; | ||
exports[`The app provider extension should show a meaningful message if an error occurs during loading 1`] = ` | ||
<main class="uk-height-viewport uk-flex uk-flex-center uk-flex-middle"> | ||
<h1 class="oc-invisible-sr">"exampleApp" app page</h1> | ||
<errorscreen-stub></errorscreen-stub> | ||
<!----> | ||
<!----> | ||
</main> | ||
`; |
Oops, something went wrong.