diff --git a/client/src/api/index.ts b/client/src/api/index.ts index 44704ca5fda5..4048356ef219 100644 --- a/client/src/api/index.ts +++ b/client/src/api/index.ts @@ -7,11 +7,19 @@ import { components } from "@/api/schema"; */ export type HistorySummary = components["schemas"]["HistorySummary"]; +export interface HistorySummaryExtended extends HistorySummary { + size: number; + contents_active: components["schemas"]["HistoryActiveContentCounts"]; + user_id: string; +} + /** * Contains additional details about a History. */ export type HistoryDetailed = components["schemas"]["HistoryDetailed"]; +export type AnyHistory = HistorySummary | HistorySummaryExtended | HistoryDetailed; + /** * Contains minimal information about a HistoryContentItem. */ @@ -125,3 +133,46 @@ export function hasDetails(entry: DatasetEntry): entry is DatasetDetails { * Contains dataset metadata information. */ export type MetadataFiles = components["schemas"]["MetadataFile"][]; + +export function isHistorySummary(history: AnyHistory): history is HistorySummary { + return !("user_id" in history); +} + +export function isHistorySummaryExtended(history: AnyHistory): history is HistorySummaryExtended { + return "contents_active" in history && "user_id" in history; +} + +type QuotaUsageResponse = components["schemas"]["UserQuotaUsage"]; + +export interface User extends QuotaUsageResponse { + id: string; + email: string; + tags_used: string[]; + isAnonymous: false; + is_admin?: boolean; + username?: string; +} + +export interface AnonymousUser { + isAnonymous: true; + username?: string; + is_admin?: false; +} + +export type GenericUser = User | AnonymousUser; + +export function isRegisteredUser(user: User | AnonymousUser | null): user is User { + return !user?.isAnonymous; +} + +export function userOwnsHistory(user: User | AnonymousUser | null, history: AnyHistory) { + return ( + // Assuming histories without user_id are owned by the current user + (isRegisteredUser(user) && !hasOwner(history)) || + (isRegisteredUser(user) && hasOwner(history) && user.id === history.user_id) + ); +} + +function hasOwner(history: AnyHistory): history is HistorySummaryExtended { + return "user_id" in history; +} diff --git a/client/src/api/schema/schema.ts b/client/src/api/schema/schema.ts index 6f7aac5f9e88..3ac2a8160ead 100644 --- a/client/src/api/schema/schema.ts +++ b/client/src/api/schema/schema.ts @@ -2336,7 +2336,6 @@ export interface components { * @description The relative URL in the form of /u/{username}/h/{slug} */ username_and_slug?: string | null; - [key: string]: unknown | undefined; }; /** ArchivedHistorySummary */ ArchivedHistorySummary: { @@ -2409,7 +2408,6 @@ export interface components { * @description The relative URL to access this item. */ url: string; - [key: string]: unknown | undefined; }; /** AsyncFile */ AsyncFile: { @@ -3597,6 +3595,153 @@ export interface components { CustomHistoryItem: { [key: string]: unknown | undefined; }; + /** CustomHistoryView */ + CustomHistoryView: { + /** + * Annotation + * @description An annotation to provide details or to help understand the purpose and usage of this item. + */ + annotation?: string | null; + /** + * Archived + * @description Whether this item has been archived and is no longer active. + */ + archived?: boolean | null; + /** + * Contents Active + * @description Contains the number of active, deleted or hidden items in a History. + */ + contents_active?: components["schemas"]["HistoryActiveContentCounts"] | null; + /** + * Contents States + * @description A dictionary keyed to possible dataset states and valued with the number of datasets in this history that have those states. + */ + contents_states?: { + [key: string]: number | undefined; + } | null; + /** + * Contents URL + * @description The relative URL to access the contents of this History. + */ + contents_url?: string | null; + /** + * Count + * @description The number of items in the history. + */ + count?: number | null; + /** + * Create Time + * @description The time and date this item was created. + */ + create_time?: string | null; + /** + * Deleted + * @description Whether this item is marked as deleted. + */ + deleted?: boolean | null; + /** + * Genome Build + * @description TODO + */ + genome_build?: string | null; + /** + * History ID + * @example 0123456789ABCDEF + */ + id?: string; + /** + * Importable + * @description Whether this History can be imported by other users with a shared link. + */ + importable?: boolean | null; + /** + * Model class + * @description The name of the database model class. + * @constant + */ + model_class?: "History"; + /** + * Name + * @description The name of the history. + */ + name?: string | null; + /** + * Nice Size + * @description The total size of the contents of this history in a human-readable format. + */ + nice_size?: string | null; + /** + * Preferred Object Store ID + * @description The ID of the object store that should be used to store new datasets in this history. + */ + preferred_object_store_id?: string | null; + /** + * Published + * @description Whether this resource is currently publicly available to all users. + */ + published?: boolean | null; + /** + * Purged + * @description Whether this item has been permanently removed. + */ + purged?: boolean | null; + /** + * Size + * @description The total size of the contents of this history in bytes. + */ + size?: number | null; + /** + * Slug + * @description Part of the URL to uniquely identify this History by link in a readable way. + */ + slug?: string | null; + /** + * State + * @description The current state of the History based on the states of the datasets it contains. + */ + state?: components["schemas"]["DatasetState"] | null; + /** + * State Counts + * @description A dictionary keyed to possible dataset states and valued with the number of datasets in this history that have those states. + */ + state_details?: { + [key: string]: number | undefined; + } | null; + /** + * State IDs + * @description A dictionary keyed to possible dataset states and valued with lists containing the ids of each HDA in that state. + */ + state_ids?: { + [key: string]: string[] | undefined; + } | null; + tags?: components["schemas"]["TagCollection"] | null; + /** + * Update Time + * @description The last time and date this item was updated. + */ + update_time?: string | null; + /** + * URL + * @deprecated + * @description The relative URL to access this item. + */ + url?: string | null; + /** + * User ID + * @description The encoded ID of the user that owns this History. + */ + user_id?: string | null; + /** + * Username + * @description Owner of the history + */ + username?: string | null; + /** + * Username and slug + * @description The relative URL in the form of /u/{username}/h/{slug} + */ + username_and_slug?: string | null; + }; /** * DCESummary * @description Dataset Collection Element summary information. @@ -6378,6 +6523,27 @@ export interface components { HelpForumUser: { [key: string]: unknown | undefined; }; + /** + * HistoryActiveContentCounts + * @description Contains the number of active, deleted or hidden items in a History. + */ + HistoryActiveContentCounts: { + /** + * Active + * @description Number of active datasets. + */ + active: number; + /** + * Deleted + * @description Number of deleted datasets. + */ + deleted: number; + /** + * Hidden + * @description Number of hidden datasets. + */ + hidden: number; + }; /** HistoryContentBulkOperationPayload */ HistoryContentBulkOperationPayload: { /** Items */ @@ -6612,27 +6778,6 @@ export interface components { * @description The relative URL in the form of /u/{username}/h/{slug} */ username_and_slug?: string | null; - [key: string]: unknown | undefined; - }; - /** - * HistoryMinimal - * @description Minimal History Response with optional fields - */ - HistoryMinimal: { - /** Id */ - id?: string | null; - /** - * Model class - * @description The name of the database model class. - * @constant - */ - model_class: "History"; - /** - * User ID - * @description The encoded ID of the user that owns this History. - */ - user_id?: string | null; - [key: string]: unknown | undefined; }; /** * HistorySummary @@ -6703,7 +6848,6 @@ export interface components { * @description The relative URL to access this item. */ url: string; - [key: string]: unknown | undefined; }; /** * Hyperlink @@ -15139,9 +15283,9 @@ export interface operations { 200: { content: { "application/json": ( + | components["schemas"]["CustomHistoryView"] | components["schemas"]["HistoryDetailed"] | components["schemas"]["HistorySummary"] - | components["schemas"]["HistoryMinimal"] )[]; }; }; @@ -15181,9 +15325,9 @@ export interface operations { content: { "application/json": | components["schemas"]["JobImportHistoryResponse"] + | components["schemas"]["CustomHistoryView"] | components["schemas"]["HistoryDetailed"] - | components["schemas"]["HistorySummary"] - | components["schemas"]["HistoryMinimal"]; + | components["schemas"]["HistorySummary"]; }; }; /** @description Validation Error */ @@ -15267,9 +15411,9 @@ export interface operations { 200: { content: { "application/json": ( + | components["schemas"]["CustomHistoryView"] | components["schemas"]["HistoryDetailed"] | components["schemas"]["HistorySummary"] - | components["schemas"]["HistoryMinimal"] )[]; }; }; @@ -15305,9 +15449,9 @@ export interface operations { 200: { content: { "application/json": ( + | components["schemas"]["CustomHistoryView"] | components["schemas"]["HistoryDetailed"] | components["schemas"]["HistorySummary"] - | components["schemas"]["HistoryMinimal"] )[]; }; }; @@ -15373,9 +15517,9 @@ export interface operations { 200: { content: { "application/json": ( + | components["schemas"]["CustomHistoryView"] | components["schemas"]["HistoryDetailed"] | components["schemas"]["HistorySummary"] - | components["schemas"]["HistoryMinimal"] )[]; }; }; @@ -15410,9 +15554,9 @@ export interface operations { 200: { content: { "application/json": + | components["schemas"]["CustomHistoryView"] | components["schemas"]["HistoryDetailed"] - | components["schemas"]["HistorySummary"] - | components["schemas"]["HistoryMinimal"]; + | components["schemas"]["HistorySummary"]; }; }; /** @description Validation Error */ @@ -15447,9 +15591,9 @@ export interface operations { 200: { content: { "application/json": + | components["schemas"]["CustomHistoryView"] | components["schemas"]["HistoryDetailed"] - | components["schemas"]["HistorySummary"] - | components["schemas"]["HistoryMinimal"]; + | components["schemas"]["HistorySummary"]; }; }; /** @description Validation Error */ @@ -15507,9 +15651,9 @@ export interface operations { 200: { content: { "application/json": + | components["schemas"]["CustomHistoryView"] | components["schemas"]["HistoryDetailed"] - | components["schemas"]["HistorySummary"] - | components["schemas"]["HistoryMinimal"]; + | components["schemas"]["HistorySummary"]; }; }; /** @description Validation Error */ @@ -15549,9 +15693,9 @@ export interface operations { 200: { content: { "application/json": ( + | components["schemas"]["CustomHistoryView"] | components["schemas"]["HistoryDetailed"] | components["schemas"]["HistorySummary"] - | components["schemas"]["HistoryMinimal"] )[]; }; }; @@ -15592,9 +15736,9 @@ export interface operations { 200: { content: { "application/json": ( + | components["schemas"]["CustomHistoryView"] | components["schemas"]["HistoryDetailed"] | components["schemas"]["HistorySummary"] - | components["schemas"]["HistoryMinimal"] )[]; }; }; @@ -15629,9 +15773,9 @@ export interface operations { 200: { content: { "application/json": + | components["schemas"]["CustomHistoryView"] | components["schemas"]["HistoryDetailed"] - | components["schemas"]["HistorySummary"] - | components["schemas"]["HistoryMinimal"]; + | components["schemas"]["HistorySummary"]; }; }; /** @description Validation Error */ @@ -15670,9 +15814,9 @@ export interface operations { 200: { content: { "application/json": + | components["schemas"]["CustomHistoryView"] | components["schemas"]["HistoryDetailed"] - | components["schemas"]["HistorySummary"] - | components["schemas"]["HistoryMinimal"]; + | components["schemas"]["HistorySummary"]; }; }; /** @description Validation Error */ @@ -15712,9 +15856,9 @@ export interface operations { 200: { content: { "application/json": + | components["schemas"]["CustomHistoryView"] | components["schemas"]["HistoryDetailed"] - | components["schemas"]["HistorySummary"] - | components["schemas"]["HistoryMinimal"]; + | components["schemas"]["HistorySummary"]; }; }; /** @description Validation Error */ @@ -15806,9 +15950,9 @@ export interface operations { 200: { content: { "application/json": + | components["schemas"]["CustomHistoryView"] | components["schemas"]["HistoryDetailed"] - | components["schemas"]["HistorySummary"] - | components["schemas"]["HistoryMinimal"]; + | components["schemas"]["HistorySummary"]; }; }; /** @description Validation Error */ diff --git a/client/src/components/History/CurrentHistory/HistoryMessages.vue b/client/src/components/History/CurrentHistory/HistoryMessages.vue index 22316dedf63f..91e06beb75fc 100644 --- a/client/src/components/History/CurrentHistory/HistoryMessages.vue +++ b/client/src/components/History/CurrentHistory/HistoryMessages.vue @@ -14,13 +14,13 @@ const props = defineProps(); const userOverQuota = ref(false); const hasMessages = computed(() => { - return userOverQuota.value || props.history.isDeleted; + return userOverQuota.value || props.history.deleted; });