mirror of
				https://github.com/gristlabs/grist-core.git
				synced 2025-06-13 20:53:59 +00:00 
			
		
		
		
	(core) Allow docs to be permanently deleted in icon view
Summary: Previously, soft-deleted docs in icon view were still accessible from the Trash and couldn't be permanently deleted. Test Plan: Improved the nbrowser test for deleting docs to verify that it can be done in both view modes. Reviewers: dsagal, paulfitz Reviewed By: dsagal Differential Revision: https://phab.getgrist.com/D2862
This commit is contained in:
		
							parent
							
								
									30bbb6fa94
								
							
						
					
					
						commit
						3af6dd46ea
					
				@ -200,7 +200,7 @@ function buildWorkspaceDocBlock(home: HomeModel, workspace: Workspace, flashDocI
 | 
			
		||||
    return dom.forEach(docs, doc => {
 | 
			
		||||
      if (view === 'icons') {
 | 
			
		||||
        return dom.update(
 | 
			
		||||
          buildPinnedDoc(home, doc),
 | 
			
		||||
          buildPinnedDoc(home, doc, workspace),
 | 
			
		||||
          testId('doc'),
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
@ -347,7 +347,7 @@ export function makeDocOptionsMenu(home: HomeModel, doc: Document, renaming: Obs
 | 
			
		||||
  ];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function makeRemovedDocOptionsMenu(home: HomeModel, doc: Document, workspace: Workspace) {
 | 
			
		||||
export function makeRemovedDocOptionsMenu(home: HomeModel, doc: Document, workspace: Workspace) {
 | 
			
		||||
  function hardDeleteDoc() {
 | 
			
		||||
    confirmModal(`Permanently Delete "${doc.name}"?`, 'Delete Forever',
 | 
			
		||||
      () => home.deleteDoc(doc.id, true).catch(reportError),
 | 
			
		||||
 | 
			
		||||
@ -103,15 +103,15 @@ function _buildExampleListDocs(home: HomeModel, workspace: Workspace, viewSettin
 | 
			
		||||
      testId('examples-desc'),
 | 
			
		||||
    ),
 | 
			
		||||
    dom.domComputed(viewSettings.currentView, (view) =>
 | 
			
		||||
      dom.forEach(workspace.docs, doc => buildExampleItem(doc, home, view))
 | 
			
		||||
      dom.forEach(workspace.docs, doc => buildExampleItem(doc, home, workspace, view))
 | 
			
		||||
    ),
 | 
			
		||||
  ];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function buildExampleItem(doc: Document, home: HomeModel, view: 'list'|'icons') {
 | 
			
		||||
function buildExampleItem(doc: Document, home: HomeModel, workspace: Workspace, view: 'list'|'icons') {
 | 
			
		||||
  const ex = examples.find((e) => e.matcher.test(doc.name));
 | 
			
		||||
  if (view === 'icons') {
 | 
			
		||||
    return buildPinnedDoc(home, doc, ex);
 | 
			
		||||
    return buildPinnedDoc(home, doc, workspace, ex);
 | 
			
		||||
  } else {
 | 
			
		||||
    return css.docRowWrapper(
 | 
			
		||||
      cssDocRowLink(
 | 
			
		||||
 | 
			
		||||
@ -1,13 +1,13 @@
 | 
			
		||||
import {docUrl, urlState} from 'app/client/models/gristUrlState';
 | 
			
		||||
import {getTimeFromNow, HomeModel} from 'app/client/models/HomeModel';
 | 
			
		||||
import {makeDocOptionsMenu} from 'app/client/ui/DocMenu';
 | 
			
		||||
import {makeDocOptionsMenu, makeRemovedDocOptionsMenu} from 'app/client/ui/DocMenu';
 | 
			
		||||
import {IExampleInfo} from 'app/client/ui/ExampleInfo';
 | 
			
		||||
import {transientInput} from 'app/client/ui/transientInput';
 | 
			
		||||
import {colors, vars} from 'app/client/ui2018/cssVars';
 | 
			
		||||
import {icon} from 'app/client/ui2018/icons';
 | 
			
		||||
import {menu} from 'app/client/ui2018/menus';
 | 
			
		||||
import * as roles from 'app/common/roles';
 | 
			
		||||
import {Document} from 'app/common/UserAPI';
 | 
			
		||||
import {Document, Workspace} from 'app/common/UserAPI';
 | 
			
		||||
import {computed, dom, makeTestId, observable, styled} from 'grainjs';
 | 
			
		||||
 | 
			
		||||
const testId = makeTestId('test-dm-');
 | 
			
		||||
@ -20,7 +20,7 @@ const testId = makeTestId('test-dm-');
 | 
			
		||||
 */
 | 
			
		||||
export function createPinnedDocs(home: HomeModel) {
 | 
			
		||||
  return pinnedDocList(
 | 
			
		||||
    dom.forEach(home.currentWSPinnedDocs, doc => buildPinnedDoc(home, doc)),
 | 
			
		||||
    dom.forEach(home.currentWSPinnedDocs, doc => buildPinnedDoc(home, doc, doc.workspace)),
 | 
			
		||||
    testId('pinned-doc-list'),
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
@ -29,15 +29,16 @@ export function createPinnedDocs(home: HomeModel) {
 | 
			
		||||
 * Build a single doc card with a preview and name. A misnomer because it's now used not only for
 | 
			
		||||
 * pinned docs, but also for the thumnbails (aka "icons") view mode.
 | 
			
		||||
 */
 | 
			
		||||
export function buildPinnedDoc(home: HomeModel, doc: Document, example?: IExampleInfo): HTMLElement {
 | 
			
		||||
export function buildPinnedDoc(home: HomeModel, doc: Document, workspace: Workspace,
 | 
			
		||||
                               example?: IExampleInfo): HTMLElement {
 | 
			
		||||
  const renaming = observable<Document|null>(null);
 | 
			
		||||
  const isRenamingDoc = computed((use) => use(renaming) === doc);
 | 
			
		||||
  const docTitle = example?.title || doc.name;
 | 
			
		||||
  return pinnedDocWrapper(
 | 
			
		||||
    dom.autoDispose(isRenamingDoc),
 | 
			
		||||
    dom.domComputed(isRenamingDoc, (isRenaming) => 
 | 
			
		||||
    dom.domComputed(isRenamingDoc, (isRenaming) =>
 | 
			
		||||
      pinnedDoc(
 | 
			
		||||
        isRenaming ? null : urlState().setLinkUrl(docUrl(doc)),
 | 
			
		||||
        isRenaming || doc.removedAt ? null : urlState().setLinkUrl(docUrl(doc)),
 | 
			
		||||
        pinnedDoc.cls('-no-access', !roles.canView(doc.access)),
 | 
			
		||||
        pinnedDocPreview(
 | 
			
		||||
          example?.bgColor ? dom.style('background-color', example.bgColor) : null,
 | 
			
		||||
@ -64,17 +65,27 @@ export function buildPinnedDoc(home: HomeModel, doc: Document, example?: IExampl
 | 
			
		||||
            )
 | 
			
		||||
          ),
 | 
			
		||||
          cssPinnedDocDesc(
 | 
			
		||||
            example?.desc || capitalizeFirst(getTimeFromNow(doc.updatedAt)),
 | 
			
		||||
            example?.desc || capitalizeFirst(getTimeFromNow(doc.removedAt || doc.updatedAt)),
 | 
			
		||||
            testId('pinned-doc-desc')
 | 
			
		||||
          )
 | 
			
		||||
        )
 | 
			
		||||
      )
 | 
			
		||||
    ),
 | 
			
		||||
    example ? null : pinnedDocOptions(icon('Dots'),
 | 
			
		||||
      menu(() => makeDocOptionsMenu(home, doc, renaming), {placement: 'bottom-start'}),
 | 
			
		||||
      // Clicks on the menu trigger shouldn't follow the link that it's contained in.
 | 
			
		||||
      dom.on('click', (ev) => { ev.stopPropagation(); ev.preventDefault(); }),
 | 
			
		||||
      testId('pinned-doc-options')
 | 
			
		||||
    example ? null : (doc.removedAt ?
 | 
			
		||||
      [
 | 
			
		||||
        // For deleted documents, attach the menu to the entire doc icon, and include the
 | 
			
		||||
        // "Dots" icon just to clarify that there are options.
 | 
			
		||||
        menu(() => makeRemovedDocOptionsMenu(home, doc, workspace),
 | 
			
		||||
          {placement: 'right-start'}),
 | 
			
		||||
        pinnedDocOptions(icon('Dots'), testId('pinned-doc-options')),
 | 
			
		||||
      ] :
 | 
			
		||||
      pinnedDocOptions(icon('Dots'),
 | 
			
		||||
        menu(() => makeDocOptionsMenu(home, doc, renaming),
 | 
			
		||||
          {placement: 'bottom-start'}),
 | 
			
		||||
        // Clicks on the menu trigger shouldn't follow the link that it's contained in.
 | 
			
		||||
        dom.on('click', (ev) => { ev.stopPropagation(); ev.preventDefault(); }),
 | 
			
		||||
        testId('pinned-doc-options'),
 | 
			
		||||
      )
 | 
			
		||||
    ),
 | 
			
		||||
    testId('pinned-doc')
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user