forked from galaxyproject/galaxy
-
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.
- Loading branch information
Showing
8 changed files
with
348 additions
and
6 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
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,209 @@ | ||
<script setup lang="ts"> | ||
import axios from "axios"; | ||
import Vue, { computed, Ref, ref, watch } from "vue"; | ||
import { enableLink, sharing } from "@/api/histories"; | ||
import { referencedObjects } from "@/components/Markdown/parse"; | ||
import { useHistoryStore } from "@/stores/historyStore"; | ||
import _l from "@/utils/localization"; | ||
import { withPrefix } from "@/utils/redirect"; | ||
import SharingIndicator from "./SharingIndicator.vue"; | ||
import LoadingSpan from "@/components/LoadingSpan.vue"; | ||
const { getHistoryNameById, loadHistoryById } = useHistoryStore(); | ||
interface ObjectPermissionsProps { | ||
markdownContent: string; | ||
} | ||
const props = defineProps<ObjectPermissionsProps>(); | ||
const referencedJobIds = ref<string[]>([]); | ||
const referencedHistoryDatasetIds = ref<string[]>([]); | ||
const referencedHistoryDatasetCollectionIds = ref<string[]>([]); | ||
const referencedWorkflowIds = ref<string[]>([]); | ||
const referencedInvocationIds = ref<string[]>([]); | ||
// We mostly defer to history permissions for all these objects. Track them... | ||
const jobsToHistories: Ref<{ [key: string]: string }> = ref({}); | ||
const invocationsToHistories: Ref<{ [key: string]: string }> = ref({}); | ||
const historyDatasetCollectionsToHistories: Ref<{ [key: string]: string }> = ref({}); | ||
const historyAccessible: Ref<{ [key: string]: Boolean | null }> = ref({}); | ||
watch(referencedJobIds, async () => { | ||
referencedJobIds.value.forEach((jobId) => { | ||
if (jobId in jobsToHistories.value) { | ||
return; | ||
} | ||
axios.get(withPrefix(`/api/jobs/${jobId}`)).then((response) => { | ||
const historyId = response.data.history_id; | ||
Vue.set(jobsToHistories.value, jobId, historyId); | ||
}); | ||
}); | ||
}); | ||
watch(referencedInvocationIds, async () => { | ||
referencedInvocationIds.value.forEach((invocationId) => { | ||
if (invocationId in invocationsToHistories.value) { | ||
return; | ||
} | ||
axios.get(withPrefix(`/api/invocations/${invocationId}`)).then((response) => { | ||
const historyId = response.data.history_id; | ||
console.log(`${invocationId} => ${historyId}`); | ||
Vue.set(invocationsToHistories.value, invocationId, historyId); | ||
}); | ||
}); | ||
}); | ||
watch(referencedInvocationIds, async () => { | ||
referencedInvocationIds.value.forEach((invocationId) => { | ||
if (invocationId in invocationsToHistories.value) { | ||
return; | ||
} | ||
axios.get(withPrefix(`/api/invocations/${invocationId}`)).then((response) => { | ||
const historyId = response.data.history_id; | ||
console.log(`${invocationId} => ${historyId}`); | ||
Vue.set(invocationsToHistories.value, invocationId, historyId); | ||
}); | ||
}); | ||
}); | ||
watch(referencedHistoryDatasetCollectionIds, async () => { | ||
referencedHistoryDatasetCollectionIds.value.forEach((historyDatasetCollectionId) => { | ||
if (historyDatasetCollectionId in historyDatasetCollectionsToHistories.value) { | ||
return; | ||
} | ||
axios.get(withPrefix(`/api/invocations/${historyDatasetCollectionId}`)).then((response) => { | ||
const historyId = response.data.history_id; | ||
console.log(`${historyDatasetCollectionId} => ${historyId}`); | ||
Vue.set(historyDatasetCollectionsToHistories.value, historyDatasetCollectionId, historyId); | ||
}); | ||
}); | ||
}); | ||
const historyIds = computed<string[]>(() => { | ||
// be sure to reference all refs required for full computation | ||
const jobIds = referencedJobIds.value; | ||
const jobMapping = jobsToHistories.value; | ||
const invocationIds = referencedInvocationIds.value; | ||
const invocationMapping = invocationsToHistories.value; | ||
const collectionIds = referencedHistoryDatasetCollectionIds.value; | ||
const collectionMapping = historyDatasetCollectionsToHistories.value; | ||
const theHistories = new Set(); | ||
for (const jobId of jobIds) { | ||
if (jobId in jobMapping) { | ||
theHistories.add(jobMapping[jobId]); | ||
} | ||
} | ||
for (const invocationId of invocationIds) { | ||
if (invocationId in invocationMapping) { | ||
theHistories.add(invocationMapping[invocationId]); | ||
} | ||
} | ||
for (const historyDatasetCollectionId of collectionIds) { | ||
if (historyDatasetCollectionId in collectionMapping) { | ||
theHistories.add(collectionMapping[historyDatasetCollectionId]); | ||
} | ||
} | ||
const historyIds = Array.from(theHistories.values()) as string[]; | ||
return historyIds; | ||
}); | ||
interface ItemInterface { | ||
id: string; | ||
accessible: Boolean | null; | ||
name: string; | ||
type: string; | ||
} | ||
const histories = computed<ItemInterface[]>(() => { | ||
return historyIds.value.map((historyId: string) => { | ||
return { | ||
id: historyId, | ||
type: "history", | ||
name: getHistoryNameById(historyId), | ||
accessible: historyAccessible.value[historyId], | ||
} as ItemInterface; | ||
}); | ||
}); | ||
const loading = ref(false); | ||
const SHARING_FIELD = { key: "accessible", label: _l("Accessible"), sortable: false, thStyle: { width: "10%" } }; | ||
const NAME_FIELD = { key: "name", label: _l("Name"), sortable: true }; | ||
const TYPE_FIELD = { key: "type", label: _l("Type"), sortable: true }; | ||
const tableFields = [SHARING_FIELD, NAME_FIELD, TYPE_FIELD]; | ||
watch( | ||
props, | ||
() => { | ||
const objects = referencedObjects(props.markdownContent); | ||
referencedJobIds.value = Array.from(objects.jobs.values()); | ||
referencedHistoryDatasetIds.value = Array.from(objects.historyDatasets.values()); | ||
referencedHistoryDatasetCollectionIds.value = Array.from(objects.historyDatasetCollections.values()); | ||
referencedWorkflowIds.value = Array.from(objects.workflows.values()); | ||
referencedInvocationIds.value = Array.from(objects.invocations.values()); | ||
}, | ||
{ immediate: true } | ||
); | ||
watch(historyIds, () => { | ||
for (const historyId of historyIds.value) { | ||
loadHistoryById(historyId); | ||
if (historyId && !(historyId in historyAccessible.value)) { | ||
Vue.set(historyAccessible.value, historyId, null); | ||
sharing({ history_id: historyId }).then((response) => { | ||
const accessible = response.data.importable; | ||
console.log(`setting ${historyId} to ${accessible}`); | ||
Vue.set(historyAccessible.value, historyId, accessible); | ||
}); | ||
} | ||
} | ||
}); | ||
const tableItems = computed<ItemInterface[]>(() => { | ||
return histories.value; | ||
}); | ||
function makeAccessible(item: ItemInterface) { | ||
if (item.type == "history") { | ||
enableLink({ history_id: item.id }).then((response) => { | ||
Vue.set(historyAccessible.value, item.id, true); | ||
}); | ||
} | ||
} | ||
</script> | ||
|
||
<template> | ||
<div> | ||
<p> | ||
Permissions for {{ markdownContent }}.... {{ jobsToHistories }} jobs are {{ referencedJobIds }} invocations | ||
are {{ referencedInvocationIds }} histories are {{ histories }} | ||
</p> | ||
|
||
<b-table :items="tableItems" :fields="tableFields"> | ||
<template v-slot:empty> | ||
<LoadingSpan v-if="loading" message="Loading objects" /> | ||
<b-alert v-else variant="info" show> | ||
<div>No objects found in referenced Galaxy markdown content.</div> | ||
</b-alert> | ||
</template> | ||
<template v-slot:cell(name)="row"> | ||
{{ row.item.name }} | ||
</template> | ||
<template v-slot:cell(accessible)="row"> | ||
<SharingIndicator :accessible="row.item.accessible" @makeAccessible="makeAccessible(row.item)" /> | ||
</template> | ||
<template v-slot:cell(type)="row"> | ||
{{ row.item.type }} | ||
</template> | ||
</b-table> | ||
</div> | ||
</template> |
15 changes: 15 additions & 0 deletions
15
client/src/components/PageEditor/ObjectPermissionsModal.vue
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,15 @@ | ||
<script setup lang="ts"> | ||
import ObjectPermissions from "./ObjectPermissions.vue"; | ||
interface ObjectPermissionsProps { | ||
markdownContent: string; | ||
} | ||
defineProps<ObjectPermissionsProps>(); | ||
</script> | ||
|
||
<template> | ||
<b-modal v-bind="$attrs" title="Page Object Permissions" title-tag="h2" ok-only v-on="$listeners"> | ||
<ObjectPermissions :markdown-content="markdownContent" /> | ||
</b-modal> | ||
</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
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,43 @@ | ||
<script setup lang="ts"> | ||
import { ref, watch } from "vue"; | ||
import LoadingSpan from "@/components/LoadingSpan.vue"; | ||
interface SharingIndicatorProps { | ||
accessible: Boolean | null; | ||
} | ||
const emit = defineEmits<{ | ||
(e: "makeAccessible"): void; | ||
}>(); | ||
const props = defineProps<SharingIndicatorProps>(); | ||
const makingAccessible = ref(false); | ||
function makeAccessible() { | ||
makingAccessible.value = true; | ||
emit("makeAccessible"); | ||
} | ||
watch(props, () => { | ||
makingAccessible.value = false; | ||
}); | ||
</script> | ||
<template> | ||
<div> | ||
<LoadingSpan v-if="accessible == null || makingAccessible" spinner-only> </LoadingSpan> | ||
<BFormCheckbox | ||
v-else | ||
switch | ||
:checked="accessible" | ||
class="make-accessible" | ||
:disabled="accessible" | ||
@change=" | ||
(event) => { | ||
makeAccessible(event); | ||
} | ||
"> | ||
</BFormCheckbox> | ||
</div> | ||
</template> |
Oops, something went wrong.