@@ -81,11 +81,14 @@ UI.aclControl.ACLControlBox5 = function (subject, dom, noun, kb, callback) {
8181
8282 // A world button can be dragged to gve public access.
8383 // later, allow it to be pressed to make pubicly viewable?
84- var publicAccessCell = bottomRow . appendChild ( dom . createElement ( 'td' ) )
85- var publicAccessButton = publicAccessCell . appendChild ( UI . widgets . button ( dom , UI . icons . iconBase + 'noun_98053.svg' , 'Public' ) )
86- UI . widgets . makeDraggable ( publicAccessButton , UI . ns . foaf ( 'Agent' ) ) // Represent everyone
84+ var bottomLeftCell = bottomRow . appendChild ( dom . createElement ( 'td' ) )
85+ // var bottomMiddleCell = bottomRow.appendChild(dom.createElement('td'))
86+ var bottomRightCell = bottomRow . appendChild ( dom . createElement ( 'td' ) )
87+
88+ // var publicAccessButton = bottomLeftCell.appendChild(UI.widgets.button(dom, UI.icons.iconBase + 'noun_98053.svg', 'Public'))
89+
90+ const bigButtonStyle = 'border-radius: 0.3em; background-color: white; border: 0.1em solid #888;'
8791
88- var bigButtonStyle = 'border-radius: 0.3em; background-color: white; border: 0.1em solid #888;'
8992
9093 // This is the main function which produces an editable access control.
9194 // There are two of these in all iff the defaults are separate
@@ -162,7 +165,7 @@ UI.aclControl.ACLControlBox5 = function (subject, dom, noun, kb, callback) {
162165 if ( ns . vcard ( 'Group' ) . uri in types ) {
163166 return { pred : 'agentGroup' , obj : obj } // @@ note vcard membership not RDFs
164167 }
165- if ( obj . sameTerm ( ns . foaf ( 'Agent' ) ) ||
168+ if ( obj . sameTerm ( ns . foaf ( 'Agent' ) ) || obj . sameTerm ( ns . acl ( 'AuthenticatedAgent' ) ) || // AuthenticatedAgent
166169 obj . sameTerm ( ns . rdf ( 'Resource' ) ) || obj . sameTerm ( ns . owl ( 'Thing' ) ) ) {
167170 return { pred : 'agentClass' , obj : obj }
168171 }
@@ -328,9 +331,14 @@ UI.aclControl.ACLControlBox5 = function (subject, dom, noun, kb, callback) {
328331 }
329332
330333 var res = agentTriage ( u ) // eg 'agent', 'origin', agentClass'
334+ const thing = $rdf . sym ( u )
331335 if ( ! res ) {
332- console . log ( ' looking up dropped thing ' + u )
333- await kb . fetcher . load ( u )
336+ console . log ( ' Not obvious: looking up dropped thing ' + thing )
337+ try {
338+ await kb . fetcher . load ( thing . doc ( ) )
339+ } catch ( err ) {
340+ console . log ( 'Ignore error looking up dropped thing: ' + err )
341+ }
334342 res = agentTriage ( u )
335343 if ( ! res ) {
336344 console . log ( ' Error: Drop fails to drop appropriate thing! ' + u )
@@ -342,10 +350,18 @@ UI.aclControl.ACLControlBox5 = function (subject, dom, noun, kb, callback) {
342350 }
343351 } // handleOneDroppedURI
344352
353+ async function addNewUIRI ( uri ) {
354+ await handleOneDroppedURI ( uri )
355+ saveAndRestoreUI ( )
356+ }
357+
345358 if ( options . modify ) {
359+ row . addNewURI = addNewUIRI
346360 UI . widgets . makeDropTarget ( row , handleManyDroppedURIs )
347361 }
348- }
362+ return row
363+ } // renderCombo
364+
349365 var syncPanel = function ( ) {
350366 var kids = box . children
351367 for ( var i = 0 ; i < kids . length ; i ++ ) {
@@ -355,13 +371,84 @@ UI.aclControl.ACLControlBox5 = function (subject, dom, noun, kb, callback) {
355371 } // @@ later -- need to addd combos not in the box?
356372 }
357373
358- var k , combo
374+
375+ function renderAdditionTool ( ele , lastRow ) {
376+ const ns = UI . ns
377+ function removeBar ( ) {
378+ ele . removeChild ( ele . bar )
379+ ele . bar = null
380+ }
381+ if ( ele . bar ) { // toggle
382+ return removeBar ( )
383+ }
384+ const bar = ele . appendChild ( dom . createElement ( 'div' ) )
385+ ele . bar = bar
386+
387+ var personButton = UI . widgets . button ( dom , UI . icons . iconBase + UI . widgets . iconForClass [ 'vcard:Individual' ] , 'Add Person' )
388+ bar . appendChild ( personButton )
389+
390+ var groupButton = UI . widgets . button ( dom , UI . icons . iconBase + UI . widgets . iconForClass [ 'vcard:Group' ] , 'Add Group' )
391+ bar . appendChild ( groupButton )
392+
393+ bar . appendChild ( UI . widgets . button ( dom , UI . icons . iconBase + UI . widgets . iconForClass [ 'foaf:Agent' ] , 'Add Everyone' , async event => {
394+ statusBlock . textContent = 'Adding the general public to those who can read. Drag the globe to a different level to give them more access.'
395+ await lastRow . addNewURI ( ns . foaf ( 'Agent' ) . uri )
396+ } ) )
397+
398+ // AuthenticatedAgent
399+ bar . appendChild ( UI . widgets . button ( dom , UI . icons . iconBase + 'noun_99101.svg' , 'Anyone logged In' , async event => {
400+ statusBlock . textContent = 'Adding the anyone logged in to those who can read. Drag the ID icon to a different level to give them more access.'
401+ await lastRow . addNewURI ( ns . acl ( 'AuthenticatedAgent' ) . uri )
402+ } ) )
403+
404+ // Bots
405+ bar . appendChild ( UI . widgets . button ( dom , UI . icons . iconBase + 'noun_Robot_849764.svg' , 'A Software Agent (bot)' , async event => {
406+ let name = await UI . widgets . askName ( dom , kb , bar , null , ns . schema ( 'WebApplication' ) , 'webapp' )
407+ if ( ! name ) return removeBar ( ) // user cancelled
408+ const domainNameRegexp = / ^ h t t p s ? : / i
409+ if ( ! name . match ( domainNameRegexp ) ) { // @@ enforce in user input live like a form element
410+ return alert ( 'Not a http URI' )
411+ }
412+ // @@ check it actually is a bot and has an owner who agrees they own it
413+ console . log ( 'Adding to ACL bot: ' + name )
414+ await lastRow . addNewURI ( name )
415+ } ) )
416+
417+ // Web Apps
418+ bar . appendChild ( UI . widgets . button ( dom , UI . icons . iconBase + 'noun_15177.svg' , 'A Web App (origin)' , async event => {
419+ console . log ( '@@ AppButton' )
420+ let name = await UI . widgets . askName ( dom , kb , bar , null , ns . schema ( 'WebApplication' ) , 'webapp' )
421+ if ( ! name ) return removeBar ( ) // user cancelled
422+ const domainNameRegexp = / ^ ( [ a - z 0 - 9 ] + ( - [ a - z 0 - 9 ] + ) * \. ) + [ a - z ] { 2 , } $ / i
423+ // https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch08s15.html
424+ if ( ! name . match ( domainNameRegexp ) ) { // @@ enforce in user input live like a form element
425+ return alert ( 'Not a domain name' )
426+ }
427+ const origin = 'https://' + name
428+ console . log ( 'Adding to ACL origin: ' + origin )
429+ await lastRow . addNewURI ( origin )
430+ } ) )
431+ }
432+
433+ function renderAddToolBar ( box , lastRow ) {
434+ const toolRow = box . appendChild ( dom . createElement ( 'tr' ) )
435+ var addButton = bottomLeftCell . appendChild ( UI . widgets . button ( dom , UI . icons . iconBase + 'noun_34653_green.svg' , 'Add ...' , event => {
436+ renderAdditionTool ( bottomLeftCell , lastRow )
437+ } ) )
438+ }
439+
440+ var k , combo , lastRow
359441 for ( k = 15 ; k > 0 ; k -- ) {
360442 combo = kToCombo ( k )
361443 if ( ( options . modify && recommended [ k ] ) || byCombo [ combo ] ) {
362- renderCombo ( byCombo , combo )
444+ lastRow = renderCombo ( byCombo , combo )
363445 } // if
364446 } // for
447+
448+ if ( options . modify ) {
449+ renderAddToolBar ( box , lastRow )
450+ }
451+
365452 return byCombo
366453 } // ACLControlEditable
367454
@@ -389,7 +476,7 @@ UI.aclControl.ACLControlBox5 = function (subject, dom, noun, kb, callback) {
389476 ACLControlEditable ( box , doc , targetACLDoc , kb2 , { modify : false } ) // Add btton to save them as actual
390477 box . style . cssText = 'color: #777;'
391478
392- var editPlease = bottomRow . appendChild ( dom . createElement ( 'button' ) )
479+ var editPlease = bottomRightCell . appendChild ( dom . createElement ( 'button' ) )
393480 editPlease . textContent = 'Set specific sharing\nfor this ' + noun
394481 editPlease . style . cssText = bigButtonStyle
395482 editPlease . addEventListener ( 'click' , function ( event ) {
@@ -399,11 +486,11 @@ UI.aclControl.ACLControlBox5 = function (subject, dom, noun, kb, callback) {
399486 statusBlock . textContent += ' (Error writing back access control file: ' + message + ')'
400487 } else {
401488 kb . add ( kb2 . statements )
402- fetcher . requested [ targetACLDoc . uri ] == = 'done' // cheat
489+ kb . fetcher . requested [ targetACLDoc . uri ] = 'done' // cheat
403490 // kb.fetcher.load(targetACLDoc, {force: true})
404491 statusBlock . textContent = ' (Now editing specific access for this ' + noun + ')'
405492 // box.style.cssText = 'color: black;'
406- bottomRow . removeChild ( editPlease )
493+ bottomRightCell . removeChild ( editPlease )
407494 renderBox ( )
408495 }
409496 } )
@@ -412,7 +499,7 @@ UI.aclControl.ACLControlBox5 = function (subject, dom, noun, kb, callback) {
412499 } else { // Not using defaults
413500 var useDefault
414501 var addDefaultButton = function ( prospectiveDefaultHolder ) {
415- useDefault = bottomRow . appendChild ( dom . createElement ( 'button' ) )
502+ useDefault = bottomRightCell . appendChild ( dom . createElement ( 'button' ) )
416503 useDefault . textContent = 'Stop specific sharing for this ' + noun +
417504 ' -- just use default' // + UI.utils.label(thisDefaultHolder)
418505 if ( prospectiveDefaultHolder ) {
@@ -475,7 +562,7 @@ UI.aclControl.ACLControlBox5 = function (subject, dom, noun, kb, callback) {
475562 box . notice . textContent = 'Sharing for things within the folder currently tracks sharing for the folder.'
476563 box . notice . style . cssText = 'font-size: 80%; color: #888;'
477564 var splitButton = UI . widgets . clearElement ( box . offer ) . appendChild ( dom . createElement ( 'button' ) )
478- splitButton . innerHTML = '<p> the sharing of folder contets <br />separately from the sharing for the folder</p>'
565+ splitButton . innerHTML = '<p>Set the sharing of folder contets <br />separately from the sharing for the folder</p>'
479566 splitButton . style . cssText = bigButtonStyle
480567 splitButton . addEventListener ( 'click' , function ( e ) {
481568 box . addControlForDefaults ( )
0 commit comments