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

UI: Always show the file browser for allocations and tasks. #9172

Merged
merged 1 commit into from
Oct 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions ui/app/routes/allocations/allocation/fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,7 @@ export default class FsRoute extends Route {
const decodedPath = decodeURIComponent(path);
const allocation = this.modelFor('allocations.allocation');

if (!allocation.isRunning) {
return {
path: decodedPath,
allocation,
};
}
if (!allocation) return;

return RSVP.all([allocation.stat(decodedPath), allocation.get('node')])
.then(([statJson]) => {
Expand Down
11 changes: 3 additions & 8 deletions ui/app/routes/allocations/allocation/task/fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,14 @@ export default class FsRoute extends Route {
model({ path = '/' }) {
const decodedPath = decodeURIComponent(path);
const taskState = this.modelFor('allocations.allocation.task');
const allocation = taskState.allocation;

if (!taskState || !taskState.allocation) return;

const allocation = taskState.allocation;
const pathWithTaskName = `${taskState.name}${
decodedPath.startsWith('/') ? '' : '/'
}${decodedPath}`;

if (!taskState.isRunning) {
return {
path: decodedPath,
taskState,
};
}

return RSVP.all([allocation.stat(pathWithTaskName), taskState.get('allocation.node')])
.then(([statJson]) => {
if (statJson.IsDir) {
Expand Down
73 changes: 32 additions & 41 deletions ui/app/templates/components/fs/browser.hbs
Original file line number Diff line number Diff line change
@@ -1,47 +1,38 @@
<section class="section is-closer {{if this.isFile "is-full-width"}}">
{{#if this.model.isRunning}}
{{#if this.isFile}}
<Fs::File @allocation={{this.allocation}} @taskState={{this.taskState}} @file={{this.path}} @stat={{this.stat}} @class="fs-explorer">
{{#if this.isFile}}
<Fs::File @allocation={{this.allocation}} @taskState={{this.taskState}} @file={{this.path}} @stat={{this.stat}} @class="fs-explorer">
<Fs::Breadcrumbs @allocation={{this.allocation}} @taskState={{this.taskState}} @path={{this.path}} />
</Fs::File>
{{else}}
<div class="fs-explorer boxed-section">
<div class="boxed-section-head">
<Fs::Breadcrumbs @allocation={{this.allocation}} @taskState={{this.taskState}} @path={{this.path}} />
</Fs::File>
{{else}}
<div class="fs-explorer boxed-section">
<div class="boxed-section-head">
<Fs::Breadcrumbs @allocation={{this.allocation}} @taskState={{this.taskState}} @path={{this.path}} />
</div>
{{#if this.directoryEntries}}
<ListTable
@source={{this.sortedDirectoryEntries}}
@sortProperty={{this.sortProperty}}
@sortDescending={{this.sortDescending}}
@class="boxed-section-body is-full-bleed is-compact" as |t|>
<t.head>
<t.sort-by @prop="Name" @class="is-two-thirds">Name</t.sort-by>
<t.sort-by @prop="Size" @class="has-text-right">File Size</t.sort-by>
<t.sort-by @prop="ModTime" @class="has-text-right">Last Modified</t.sort-by>
</t.head>
<t.body as |row|>
<Fs::DirectoryEntry @path={{this.path}} @allocation={{this.allocation}} @taskState={{this.taskState}} @entry={{row.model}} />
</t.body>
</ListTable>
{{else}}
<div class="boxed-section-body">
<div data-test-empty-directory class="empty-message">
<h3 data-test-empty-directory-headline class="empty-message-headline">No Files</h3>
<p data-test-empty-directory-body class="empty-message-body">
Directory is currently empty.
</p>
</div>
</div>
{{/if}}
</div>
{{/if}}
{{else}}
<div data-test-not-running class="empty-message">
<h3 data-test-not-running-headline class="empty-message-headline">{{capitalize this.type}} is not Running</h3>
<p data-test-not-running-body class="empty-message-body">
Cannot access files of a{{if this.allocation 'n'}} {{this.type}} that is not running.
</p>
{{#if this.directoryEntries}}
<ListTable
@source={{this.sortedDirectoryEntries}}
@sortProperty={{this.sortProperty}}
@sortDescending={{this.sortDescending}}
@class="boxed-section-body is-full-bleed is-compact" as |t|>
<t.head>
<t.sort-by @prop="Name" @class="is-two-thirds">Name</t.sort-by>
<t.sort-by @prop="Size" @class="has-text-right">File Size</t.sort-by>
<t.sort-by @prop="ModTime" @class="has-text-right">Last Modified</t.sort-by>
</t.head>
<t.body as |row|>
<Fs::DirectoryEntry @path={{this.path}} @allocation={{this.allocation}} @taskState={{this.taskState}} @entry={{row.model}} />
</t.body>
</ListTable>
{{else}}
<div class="boxed-section-body">
<div data-test-empty-directory class="empty-message">
<h3 data-test-empty-directory-headline class="empty-message-headline">No Files</h3>
<p data-test-empty-directory-body class="empty-message-body">
Directory is currently empty.
</p>
</div>
</div>
{{/if}}
</div>
{{/if}}
</section>
23 changes: 1 addition & 22 deletions ui/tests/acceptance/allocation-fs-test.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
/* eslint-disable ember-a11y-testing/a11y-audit-called */ // Covered in behaviours/fs
import { module, test } from 'qunit';
import { module } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';

import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
import Response from 'ember-cli-mirage/response';

import browseFilesystem from './behaviors/fs';

import FS from 'nomad-ui/tests/pages/allocations/fs';

let allocation;
let files;

Expand Down Expand Up @@ -48,24 +45,6 @@ module('Acceptance | allocation fs', function(hooks) {
this.nestedDirectory = files[1];
});

test('when the allocation is not running, an empty state is shown', async function(assert) {
// The API 500s on stat when not running
this.server.get('/client/fs/stat/:allocation_id', () => {
return new Response(500, {}, 'no such file or directory');
});

allocation.update({
clientStatus: 'complete',
});

await FS.visitAllocation({ id: allocation.id });
assert.ok(FS.hasEmptyState, 'Non-running allocation has no files');
assert.ok(
FS.emptyState.headline.includes('Allocation is not Running'),
'Empty state explains the condition'
);
});

browseFilesystem({
visitSegments: ({ allocation }) => ({ id: allocation.id }),
getExpectedPathBase: ({ allocation }) => `/allocations/${allocation.id}/fs/`,
Expand Down
47 changes: 18 additions & 29 deletions ui/tests/acceptance/task-fs-test.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
/* eslint-disable ember-a11y-testing/a11y-audit-called */ // Covered in behaviours/fs
import { module, test } from 'qunit';
import { module } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';

import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
import Response from 'ember-cli-mirage/response';

import browseFilesystem from './behaviors/fs';

import FS from 'nomad-ui/tests/pages/allocations/fs';

let allocation;
let task;
let files, taskDirectory, directory, nestedDirectory;
Expand Down Expand Up @@ -37,10 +34,18 @@ module('Acceptance | task fs', function(hooks) {
files.push(taskDirectory);

// Nested files
directory = server.create('allocFile', { isDir: true, name: 'directory', parent: taskDirectory });
directory = server.create('allocFile', {
isDir: true,
name: 'directory',
parent: taskDirectory,
});
files.push(directory);

nestedDirectory = server.create('allocFile', { isDir: true, name: 'another', parent: directory });
nestedDirectory = server.create('allocFile', {
isDir: true,
name: 'another',
parent: directory,
});
files.push(nestedDirectory);

files.push(
Expand All @@ -51,7 +56,9 @@ module('Acceptance | task fs', function(hooks) {
})
);

files.push(server.create('allocFile', { isDir: true, name: 'empty-directory', parent: taskDirectory }));
files.push(
server.create('allocFile', { isDir: true, name: 'empty-directory', parent: taskDirectory })
);
files.push(server.create('allocFile', 'file', { fileType: 'txt', parent: taskDirectory }));
files.push(server.create('allocFile', 'file', { fileType: 'txt', parent: taskDirectory }));

Expand All @@ -60,29 +67,11 @@ module('Acceptance | task fs', function(hooks) {
this.nestedDirectory = nestedDirectory;
});

test('when the task is not running, an empty state is shown', async function(assert) {
// The API 500s on stat when not running
this.server.get('/client/fs/stat/:allocation_id', () => {
return new Response(500, {}, 'no such file or directory');
});

task.update({
finishedAt: new Date(),
});

await FS.visitTask({ id: allocation.id, name: task.name });
assert.ok(FS.hasEmptyState, 'Non-running task has no files');
assert.ok(
FS.emptyState.headline.includes('Task is not Running'),
'Empty state explains the condition'
);
});

browseFilesystem({
visitSegments: ({allocation,task}) => ({ id: allocation.id, name: task.name }),
getExpectedPathBase: ({allocation,task}) => `/allocations/${allocation.id}/${task.name}/fs/`,
getTitleComponent: ({task}) => `Task ${task.name} filesystem`,
getBreadcrumbComponent: ({task}) => task.name,
visitSegments: ({ allocation, task }) => ({ id: allocation.id, name: task.name }),
getExpectedPathBase: ({ allocation, task }) => `/allocations/${allocation.id}/${task.name}/fs/`,
getTitleComponent: ({ task }) => `Task ${task.name} filesystem`,
getBreadcrumbComponent: ({ task }) => task.name,
getFilesystemRoot: ({ task }) => task.name,
pageObjectVisitFunctionName: 'visitTask',
pageObjectVisitPathFunctionName: 'visitTaskPath',
Expand Down